sentinel_crypto/encrypt/
encryption_key.rs1use crate::error::CryptoError;
2
3pub struct EncryptionKeyManager;
5
6impl EncryptionKeyManager {
7 pub fn generate_key() -> [u8; 32] { rand::random() }
9
10 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 pub fn export_key(key: &[u8; 32]) -> String { hex::encode(key) }
19
20 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 pub async fn derive_key_from_passphrase(passphrase: &str) -> Result<(Vec<u8>, [u8; 32]), CryptoError> {
32 crate::derive_key_from_passphrase(passphrase).await
33 }
34
35 pub async 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).await
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 #[tokio::test]
68 #[serial_test::serial]
69 async fn test_derive_key() {
70 crate::crypto_config::reset_global_crypto_config_for_tests().await;
71 let config = crate::CryptoConfig {
72 hash_algorithm: crate::HashAlgorithmChoice::Blake3,
73 signature_algorithm: crate::SignatureAlgorithmChoice::Ed25519,
74 encryption_algorithm: crate::EncryptionAlgorithmChoice::XChaCha20Poly1305,
75 key_derivation_algorithm: crate::KeyDerivationAlgorithmChoice::Argon2id,
76 };
77 let _ = crate::set_global_crypto_config(config).await;
78
79 let (salt1, key1) = EncryptionKeyManager::derive_key_from_passphrase("test")
80 .await
81 .unwrap();
82 assert_eq!(key1.len(), 32);
83 assert_eq!(salt1.len(), 32);
84
85 let key1_again = EncryptionKeyManager::derive_key_from_passphrase_with_salt("test", &salt1)
87 .await
88 .unwrap();
89 assert_eq!(key1, key1_again);
90
91 let (_salt2, key2) = EncryptionKeyManager::derive_key_from_passphrase("different")
93 .await
94 .unwrap();
95 assert_ne!(key1, key2);
96 }
97
98 #[tokio::test]
99 #[serial_test::serial]
100 async fn test_derive_key_pbkdf2() {
101 crate::crypto_config::reset_global_crypto_config_for_tests().await;
102 let config = crate::CryptoConfig {
103 hash_algorithm: crate::HashAlgorithmChoice::Blake3,
104 signature_algorithm: crate::SignatureAlgorithmChoice::Ed25519,
105 encryption_algorithm: crate::EncryptionAlgorithmChoice::XChaCha20Poly1305,
106 key_derivation_algorithm: crate::KeyDerivationAlgorithmChoice::Pbkdf2,
107 };
108 let _ = crate::set_global_crypto_config(config).await;
109
110 let (salt1, key1) = EncryptionKeyManager::derive_key_from_passphrase("test")
111 .await
112 .unwrap();
113 assert_eq!(key1.len(), 32);
114 assert_eq!(salt1.len(), 32);
115
116 let key1_again = EncryptionKeyManager::derive_key_from_passphrase_with_salt("test", &salt1)
118 .await
119 .unwrap();
120 assert_eq!(key1, key1_again);
121
122 let (_salt2, key2) = EncryptionKeyManager::derive_key_from_passphrase("different")
124 .await
125 .unwrap();
126 assert_ne!(key1, key2);
127 }
128}