extern crate alloc;
use alloc::{format, vec, vec::Vec};
use fn_dsa::{
sign_key_size, vrfy_key_size, signature_size, FN_DSA_LOGN_512,
KeyPairGenerator, KeyPairGenerator512,
SigningKey, SigningKey512,
VerifyingKey, VerifyingKey512,
DOMAIN_NONE, HASH_ID_RAW,
};
use rand_core::{CryptoRng, RngCore};
use crate::error::{SigError, SigResult};
use crate::types::{SigAlgorithm, SigPublicKey, SigSecretKey, Signature};
pub struct FnDsa512Keypair {
sign_key: Vec<u8>,
vrfy_key: Vec<u8>,
}
impl FnDsa512Keypair {
pub fn generate<R: CryptoRng + RngCore>(rng: &mut R) -> SigResult<Self> {
let mut sign_key = vec![0u8; sign_key_size(FN_DSA_LOGN_512)];
let mut vrfy_key = vec![0u8; vrfy_key_size(FN_DSA_LOGN_512)];
let mut kg = KeyPairGenerator512::default();
kg.keygen(FN_DSA_LOGN_512, rng, &mut sign_key, &mut vrfy_key);
Ok(Self { sign_key, vrfy_key })
}
pub fn public_key(&self) -> SigPublicKey {
SigPublicKey::new(SigAlgorithm::FnDsa512, self.vrfy_key.clone())
}
pub fn secret_key(&self) -> SigSecretKey {
SigSecretKey::new(SigAlgorithm::FnDsa512, self.sign_key.clone())
}
pub fn sign<R: CryptoRng + RngCore>(&self, rng: &mut R, message: &[u8]) -> SigResult<Signature> {
let mut sk = SigningKey512::decode(&self.sign_key)
.ok_or_else(|| SigError::InvalidSecretKey("malformed FN-DSA-512 signing key".into()))?;
let mut sig = vec![0u8; signature_size(FN_DSA_LOGN_512)];
sk.sign(rng, &DOMAIN_NONE, &HASH_ID_RAW, message, &mut sig)
.ok_or_else(|| SigError::Signing("fn-dsa signing failed".into()))?;
Ok(Signature::new(SigAlgorithm::FnDsa512, sig))
}
pub fn verify(public_key: &SigPublicKey, message: &[u8], signature: &Signature) -> SigResult<()> {
if public_key.algorithm != SigAlgorithm::FnDsa512 {
return Err(SigError::InvalidPublicKey(
format!("expected FN-DSA-512 key, got {:?}", public_key.algorithm)
));
}
if signature.algorithm != SigAlgorithm::FnDsa512 {
return Err(SigError::InvalidSignature(
format!("expected FN-DSA-512 signature, got {:?}", signature.algorithm)
));
}
let vk = VerifyingKey512::decode(&public_key.bytes)
.ok_or_else(|| SigError::InvalidPublicKey("malformed FN-DSA-512 public key".into()))?;
if vk.verify(&signature.bytes, &DOMAIN_NONE, &HASH_ID_RAW, message) {
Ok(())
} else {
Err(SigError::VerificationFailed)
}
}
pub fn from_key_bytes(pk_bytes: &[u8], sk_bytes: &[u8]) -> SigResult<Self> {
VerifyingKey512::decode(pk_bytes)
.ok_or_else(|| SigError::InvalidPublicKey("malformed FN-DSA-512 public key".into()))?;
SigningKey512::decode(sk_bytes)
.ok_or_else(|| SigError::InvalidSecretKey("malformed FN-DSA-512 signing key".into()))?;
Ok(Self { sign_key: sk_bytes.to_vec(), vrfy_key: pk_bytes.to_vec() })
}
}