#![cfg_attr(docsrs, doc(cfg(feature = "safe_api")))]
pub use crate::KP;
pub use crate::hazardous::dsa::mldsa65::Seed;
pub use crate::hazardous::dsa::mldsa65::Signature;
pub use crate::hazardous::dsa::mldsa65::VerifyingKey;
use crate::{errors::UnknownCryptoError, hazardous::dsa::mldsa65};
#[derive(Debug, PartialEq)]
pub struct SigningKeyPair {
kp: mldsa65::KeyPair,
}
impl KP<mldsa65::MlDsaSeed, mldsa65::MlDsa65VerifyingKey> for SigningKeyPair {
fn private(&self) -> &Seed {
self.kp.seed()
}
fn public(&self) -> &VerifyingKey {
&self.kp.verifying_key
}
}
impl SigningKeyPair {
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn generate() -> Result<Self, UnknownCryptoError> {
let seed = Seed::generate()?;
Ok(Self {
kp: mldsa65::KeyPair::try_from(&seed)?,
})
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn sign(&self, m: &[u8], ctx: &[u8]) -> Result<Signature, UnknownCryptoError> {
self.kp.signing_key.sign(m, ctx)
}
#[must_use = "SECURITY WARNING: Ignoring a Result can have real security implications."]
pub fn verify(&self, m: &[u8], ctx: &[u8], sig: &Signature) -> Result<(), UnknownCryptoError> {
self.kp.verifying_key.verify(m, ctx, sig)
}
}
impl TryFrom<&Seed> for SigningKeyPair {
type Error = UnknownCryptoError;
fn try_from(value: &Seed) -> Result<Self, Self::Error> {
Ok(Self {
kp: mldsa65::KeyPair::try_from(value)?,
})
}
}
#[cfg(feature = "safe_api")]
#[cfg(test)]
mod public {
use super::*;
#[test]
fn test_keypair() {
let seed = Seed::from([0u8; 32]);
let kp = SigningKeyPair::try_from(&seed).unwrap();
assert_eq!(kp.private(), &seed);
assert_eq!(
kp.public(),
&VerifyingKey::try_from(kp.kp.verifying_key.as_ref()).unwrap()
);
}
#[quickcheck]
fn prop_sign_verify(input: Vec<u8>) -> bool {
let kp = SigningKeyPair::generate().unwrap();
let sig = kp.sign(&input, &[]).unwrap();
kp.verify(&input, &[], &sig).is_ok()
}
}