flcrypto 0.10.0

Cryptographic package for different algorithms
Documentation
use std::fmt::Debug;

use bytes::Bytes;
use pqcrypto_mldsa::{mldsa44, mldsa65, mldsa87};
use pqcrypto_traits::sign::DetachedSignature;
use serde::{Deserialize, Serialize};

use crate::{
    signer::{KeyPairID, Signature, Signer, SignerError, SignerTrait, Verifier, VerifierTrait},
    tofrombytes::ToFromBytes,
};

#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub enum SignerMlDSA {
    MlDSA44(mldsa44::PublicKey, mldsa44::SecretKey),
    MlDSA65(mldsa65::PublicKey, mldsa65::SecretKey),
    MlDSA87(mldsa87::PublicKey, mldsa87::SecretKey),
}

impl SignerTrait for SignerMlDSA {
    fn sign(&self, msg: &Bytes) -> anyhow::Result<Signature> {
        Ok(match self {
            SignerMlDSA::MlDSA44(_, secret_key) => {
                Bytes::copy_from_slice(mldsa44::detached_sign(msg, secret_key).as_bytes())
            }
            SignerMlDSA::MlDSA65(_, secret_key) => {
                Bytes::copy_from_slice(mldsa65::detached_sign(msg, secret_key).as_bytes())
            }
            SignerMlDSA::MlDSA87(_, secret_key) => {
                Bytes::copy_from_slice(mldsa87::detached_sign(msg, secret_key).as_bytes())
            }
        })
    }

    fn verifier(&self) -> Verifier {
        Verifier::MlDSA(match self {
            SignerMlDSA::MlDSA44(public_key, _) => VerifierMlDSA::MlDSA44(public_key.clone()),
            SignerMlDSA::MlDSA65(public_key, _) => VerifierMlDSA::MlDSA65(public_key.clone()),
            SignerMlDSA::MlDSA87(public_key, _) => VerifierMlDSA::MlDSA87(public_key.clone()),
        })
    }

    fn get_id(&self) -> KeyPairID {
        self.verifier().get_id()
    }
}

impl SignerMlDSA {
    pub fn new44() -> Signer {
        let (pk, sk) = mldsa44::keypair();
        Signer::MlDSA(Self::MlDSA44(pk, sk))
    }

    pub fn new65() -> Signer {
        let (pk, sk) = mldsa65::keypair();
        Signer::MlDSA(Self::MlDSA65(pk, sk))
    }

    pub fn new87() -> Signer {
        let (pk, sk) = mldsa87::keypair();
        Signer::MlDSA(Self::MlDSA87(pk, sk))
    }
}

impl Debug for SignerMlDSA {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::MlDSA44(_, _) => f.debug_tuple("MlDSA44").finish(),
            Self::MlDSA65(_, _) => f.debug_tuple("MlDSA65").finish(),
            Self::MlDSA87(_, _) => f.debug_tuple("MlDSA87").finish(),
        }
    }
}

#[derive(Serialize, Deserialize, Clone, PartialEq)]
pub enum VerifierMlDSA {
    MlDSA44(mldsa44::PublicKey),
    MlDSA65(mldsa65::PublicKey),
    MlDSA87(mldsa87::PublicKey),
}

impl VerifierTrait for VerifierMlDSA {
    fn verify(&self, msg: &Bytes, sig: &Bytes) -> anyhow::Result<()> {
        match self {
            VerifierMlDSA::MlDSA44(public_key) => {
                let ds = mldsa44::DetachedSignature::from_bytes(sig)
                    .map_err(|e| SignerError::PQCrypto(format!("Signature error {e:?}")))?;
                mldsa44::verify_detached_signature(&ds, msg, public_key)
                    .map_err(|_| SignerError::SignatureMessageMismatch.into())
            }
            VerifierMlDSA::MlDSA65(public_key) => {
                let ds = mldsa65::DetachedSignature::from_bytes(sig)
                    .map_err(|e| SignerError::PQCrypto(format!("Signature error {e:?}")))?;
                mldsa65::verify_detached_signature(&ds, msg, public_key)
                    .map_err(|_| SignerError::SignatureMessageMismatch.into())
            }
            VerifierMlDSA::MlDSA87(public_key) => {
                let ds = mldsa87::DetachedSignature::from_bytes(sig)
                    .map_err(|e| SignerError::PQCrypto(format!("Signature error {e:?}")))?;
                mldsa87::verify_detached_signature(&ds, msg, public_key)
                    .map_err(|_| SignerError::SignatureMessageMismatch.into())
            }
        }
    }

    fn get_id(&self) -> KeyPairID {
        KeyPairID::hash_domain_parts(&format!("{:?}", self), &[&self.to_rmp_bytes()])
    }
}

impl Debug for VerifierMlDSA {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Self::MlDSA44(_) => f.debug_tuple("MlDSA44").finish(),
            Self::MlDSA65(_) => f.debug_tuple("MlDSA65").finish(),
            Self::MlDSA87(_) => f.debug_tuple("MlDSA87").finish(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_sign() -> anyhow::Result<()> {
        sign_verify(SignerMlDSA::new44())?;
        sign_verify(SignerMlDSA::new65())?;
        sign_verify(SignerMlDSA::new87())?;
        Ok(())
    }

    fn sign_verify(signer: Signer) -> anyhow::Result<()> {
        let msg = Bytes::from("123");
        let sig = signer.sign(&msg)?;
        let ver = signer.verifier();
        ver.verify(&msg, &sig)
    }
}