quantum_shield/
keys.rs

1//! Key management for hybrid cryptography
2
3use crate::{Error, Result};
4use serde::{Deserialize, Serialize};
5use zeroize::Zeroize;
6
7/// Public keys bundle for hybrid cryptography
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct PublicKeys {
10    /// RSA-4096 public key (PEM format)
11    pub rsa_pem: String,
12    
13    /// Kyber-1024 public key (base64)
14    pub kyber_base64: String,
15    
16    /// Dilithium5 public key (base64)
17    pub dilithium_base64: String,
18    
19    /// Version for compatibility
20    pub version: u32,
21}
22
23impl PublicKeys {
24    /// Create a new public keys bundle
25    pub fn new(rsa_pem: String, kyber_base64: String, dilithium_base64: String) -> Self {
26        Self {
27            rsa_pem,
28            kyber_base64,
29            dilithium_base64,
30            version: 1,
31        }
32    }
33    
34    /// Serialize to JSON
35    pub fn to_json(&self) -> Result<String> {
36        serde_json::to_string(self).map_err(|e| Error::SerializationError(e.to_string()))
37    }
38    
39    /// Deserialize from JSON
40    pub fn from_json(json: &str) -> Result<Self> {
41        serde_json::from_str(json).map_err(|e| Error::SerializationError(e.to_string()))
42    }
43}
44
45/// Private keys (zeroized on drop for security)
46#[derive(Zeroize)]
47#[zeroize(drop)]
48pub struct PrivateKeys {
49    /// RSA-4096 private key (PEM format)
50    pub(crate) rsa_pem: String,
51    
52    /// Kyber-1024 private key (binary)
53    pub(crate) kyber_bytes: Vec<u8>,
54    
55    /// Dilithium5 private key (binary)
56    pub(crate) dilithium_bytes: Vec<u8>,
57}
58
59impl PrivateKeys {
60    /// Create a new private keys bundle
61    pub(crate) fn new(rsa_pem: String, kyber_bytes: Vec<u8>, dilithium_bytes: Vec<u8>) -> Self {
62        Self {
63            rsa_pem,
64            kyber_bytes,
65            dilithium_bytes,
66        }
67    }
68}
69
70/// Complete keypair (public + private)
71pub struct KeyPair {
72    /// Public keys
73    pub(crate) public: PublicKeys,
74    
75    /// Private keys
76    pub(crate) private: PrivateKeys,
77}
78
79impl KeyPair {
80    /// Get public keys
81    pub fn public_keys(&self) -> &PublicKeys {
82        &self.public
83    }
84    
85    /// Get private keys (internal use only)
86    pub(crate) fn private_keys(&self) -> &PrivateKeys {
87        &self.private
88    }
89}
90
91#[cfg(test)]
92mod tests {
93    use super::*;
94
95    #[test]
96    fn test_public_keys_serialization() {
97        let keys = PublicKeys::new(
98            "-----BEGIN PUBLIC KEY-----\ntest\n-----END PUBLIC KEY-----".to_string(),
99            "kyber_key".to_string(),
100            "dilithium_key".to_string(),
101        );
102        
103        let json = keys.to_json().unwrap();
104        let keys2 = PublicKeys::from_json(&json).unwrap();
105        
106        assert_eq!(keys.rsa_pem, keys2.rsa_pem);
107        assert_eq!(keys.kyber_base64, keys2.kyber_base64);
108    }
109
110    #[test]
111    fn test_private_keys_zeroize() {
112        let mut private = PrivateKeys::new(
113            "private_key".to_string(),
114            vec![1, 2, 3],
115            vec![4, 5, 6],
116        );
117        
118        // Keys should be zeroized on drop
119        drop(private);
120    }
121}
122