sentinel_crypto/encrypt/
encryption_key.rs

1use crate::error::CryptoError;
2
3/// Encryption key management utilities
4pub struct EncryptionKeyManager;
5
6impl EncryptionKeyManager {
7    /// Generate a new random 256-bit encryption key
8    pub fn generate_key() -> [u8; 32] { rand::random() }
9
10    /// Rotate key: generate new key and return both old and new
11    /// For rotation, you might want to re-encrypt data with the new key
12    pub fn rotate_key(_old_key: &[u8; 32]) -> ([u8; 32], [u8; 32]) {
13        let new_key = Self::generate_key();
14        (*_old_key, new_key)
15    }
16
17    /// Export key as hex
18    pub fn export_key(key: &[u8; 32]) -> String { hex::encode(key) }
19
20    /// Import key from hex
21    pub fn import_key(hex: &str) -> Result<[u8; 32], CryptoError> {
22        let bytes = hex::decode(hex).map_err(CryptoError::Hex)?;
23        let array: [u8; 32] = bytes
24            .as_slice()
25            .try_into()
26            .map_err(|_| CryptoError::InvalidKeyLength)?;
27        Ok(array)
28    }
29
30    /// Generate a key from a passphrase using the default KDF
31    pub fn derive_key_from_passphrase(passphrase: &str) -> Result<(Vec<u8>, [u8; 32]), CryptoError> {
32        crate::derive_key_from_passphrase(passphrase)
33    }
34
35    /// Generate a key from a passphrase using the provided salt
36    pub fn derive_key_from_passphrase_with_salt(passphrase: &str, salt: &[u8]) -> Result<[u8; 32], CryptoError> {
37        crate::derive_key_from_passphrase_with_salt(passphrase, salt)
38    }
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    #[test]
46    fn test_generate_key() {
47        let key = EncryptionKeyManager::generate_key();
48        assert_eq!(key.len(), 32);
49    }
50
51    #[test]
52    fn test_export_import_key() {
53        let key = EncryptionKeyManager::generate_key();
54        let hex = EncryptionKeyManager::export_key(&key);
55        let imported = EncryptionKeyManager::import_key(&hex).unwrap();
56        assert_eq!(key, imported);
57    }
58
59    #[test]
60    fn test_rotate_key() {
61        let old_key = EncryptionKeyManager::generate_key();
62        let (returned_old, new_key) = EncryptionKeyManager::rotate_key(&old_key);
63        assert_eq!(old_key, returned_old);
64        assert_ne!(old_key, new_key);
65    }
66
67    #[test]
68    fn test_derive_key() {
69        let (salt1, key1) = EncryptionKeyManager::derive_key_from_passphrase("test").unwrap();
70        assert_eq!(key1.len(), 32);
71        assert_eq!(salt1.len(), 32);
72
73        // Same passphrase with same salt should give same key
74        let key1_again = EncryptionKeyManager::derive_key_from_passphrase_with_salt("test", &salt1).unwrap();
75        assert_eq!(key1, key1_again);
76
77        // Different passphrase should give different key
78        let (_salt2, key2) = EncryptionKeyManager::derive_key_from_passphrase("different").unwrap();
79        assert_ne!(key1, key2);
80    }
81}