quantcrypt/dsa/api/
key_generator.rs

1use crate::asn1::private_key::PrivateKey;
2use crate::asn1::public_key::PublicKey;
3use crate::dsa::common::config::oids::Oid;
4use crate::dsa::{api::algorithm::DsaAlgorithm, common::dsa_trait::Dsa, dsa_manager::DsaManager};
5use crate::errors;
6
7type Result<T> = std::result::Result<T, errors::QuantCryptError>;
8
9/// A key generator for DSA keys
10///
11/// # Example
12/// ```
13/// use quantcrypt::dsas::DsaKeyGenerator;
14/// use quantcrypt::dsas::DsaAlgorithm;
15///
16/// let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa44);
17/// let (pk, sk) = key_generator.generate().unwrap();
18///
19/// let msg = b"Hello, world!";
20///
21/// let sig = sk.sign(msg).unwrap();
22/// assert!(pk.verify(msg, &sig).unwrap());
23/// ```
24pub struct DsaKeyGenerator {
25    /// The algorithm to use for key generation
26    algorithm: DsaAlgorithm,
27}
28
29impl DsaKeyGenerator {
30    /// Create a new `DsaKeyGenerator` with the specified algorithm
31    ///
32    /// # Arguments
33    ///
34    /// * `algorithm` - The algorithm to use for key generation
35    ///
36    /// # Returns
37    ///
38    /// The new `KeyGenerator`
39    pub fn new(algorithm: DsaAlgorithm) -> DsaKeyGenerator {
40        DsaKeyGenerator { algorithm }
41    }
42
43    /// Generate a keypair using the default RNG
44    ///
45    /// # Returns
46    ///
47    /// A tuple containing the public and secret keys (pk, sk)
48    pub fn generate(&mut self) -> Result<(PublicKey, PrivateKey)> {
49        let dsa_type = self.algorithm.get_dsa_type();
50        let mut dsa_manager = DsaManager::new(dsa_type.clone())?;
51        let (pk, sk) = dsa_manager.key_gen()?;
52        let oid = dsa_type.get_oid();
53        let pk = PublicKey::new(&oid, &pk)?;
54        let sk = PrivateKey::new(&oid, &sk, Some(pk.clone()))?;
55        Ok((pk, sk))
56    }
57}
58
59#[cfg(test)]
60mod test {
61    use crate::dsa::api::algorithm::DsaAlgorithm;
62    use crate::dsa::api::key_generator::DsaKeyGenerator;
63
64    #[test]
65    fn test_key_generator_sign_verify() {
66        // Try a pure algorithm
67        let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa44);
68        let (pk, sk) = key_generator.generate().unwrap();
69        assert_eq!(pk.get_oid(), DsaAlgorithm::MlDsa44.get_oid());
70        assert_eq!(sk.get_oid(), DsaAlgorithm::MlDsa44.get_oid());
71
72        let msg = b"Hello, world!";
73        let sig = sk.sign(msg).unwrap();
74        assert!(pk.verify(msg, &sig).unwrap());
75
76        // Try a composite algorithm EC based
77        let mut key_generator =
78            DsaKeyGenerator::new(DsaAlgorithm::MlDsa44EcdsaBrainpoolP256r1SHA256);
79        let (pk, sk) = key_generator.generate().unwrap();
80        assert_eq!(
81            pk.get_oid(),
82            DsaAlgorithm::MlDsa44EcdsaBrainpoolP256r1SHA256.get_oid()
83        );
84        assert_eq!(
85            sk.get_oid(),
86            DsaAlgorithm::MlDsa44EcdsaBrainpoolP256r1SHA256.get_oid()
87        );
88        let sig = sk.sign(msg).unwrap();
89        assert!(pk.verify(msg, &sig).unwrap());
90
91        // Try a composite algorithm RSA PSS based
92        let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa44Rsa2048PssSha256);
93        let (pk, sk) = key_generator.generate().unwrap();
94        assert_eq!(
95            pk.get_oid(),
96            DsaAlgorithm::MlDsa44Rsa2048PssSha256.get_oid()
97        );
98        assert_eq!(
99            sk.get_oid(),
100            DsaAlgorithm::MlDsa44Rsa2048PssSha256.get_oid()
101        );
102        let sig = sk.sign(msg).unwrap();
103        assert!(pk.verify(msg, &sig).unwrap());
104
105        // Try a composite algorithm RSA PKCS1 based
106        let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa44Rsa2048Pkcs15Sha256);
107        let (pk, sk) = key_generator.generate().unwrap();
108        assert_eq!(
109            pk.get_oid(),
110            DsaAlgorithm::MlDsa44Rsa2048Pkcs15Sha256.get_oid()
111        );
112        assert_eq!(
113            sk.get_oid(),
114            DsaAlgorithm::MlDsa44Rsa2048Pkcs15Sha256.get_oid()
115        );
116        let sig = sk.sign(msg).unwrap();
117        assert!(pk.verify(msg, &sig).unwrap());
118
119        // Try a composite algorithm X25519 based
120        let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa44Ed25519SHA512);
121        let (pk, sk) = key_generator.generate().unwrap();
122        assert_eq!(pk.get_oid(), DsaAlgorithm::MlDsa44Ed25519SHA512.get_oid());
123        assert_eq!(sk.get_oid(), DsaAlgorithm::MlDsa44Ed25519SHA512.get_oid());
124        let sig = sk.sign(msg).unwrap();
125        assert!(pk.verify(msg, &sig).unwrap());
126
127        // Try a composite algorithm X448 based
128        let mut key_generator = DsaKeyGenerator::new(DsaAlgorithm::MlDsa87Ed448SHA512);
129        let (pk, sk) = key_generator.generate().unwrap();
130        assert_eq!(pk.get_oid(), DsaAlgorithm::MlDsa87Ed448SHA512.get_oid());
131        assert_eq!(sk.get_oid(), DsaAlgorithm::MlDsa87Ed448SHA512.get_oid());
132        let sig = sk.sign(msg).unwrap();
133        assert!(pk.verify(msg, &sig).unwrap());
134    }
135}