this repo has no description
1#[allow(deprecated)]
2use aes_gcm::{Aes256Gcm, KeyInit, Nonce, aead::Aead};
3use hkdf::Hkdf;
4use sha2::Sha256;
5
6use crate::CryptoError;
7
8pub fn derive_key(master_key: &[u8], context: &[u8]) -> Result<[u8; 32], CryptoError> {
9 let hk = Hkdf::<Sha256>::new(None, master_key);
10 let mut output = [0u8; 32];
11 hk.expand(context, &mut output)
12 .map_err(|e| CryptoError::KeyDerivationFailed(format!("{}", e)))?;
13 Ok(output)
14}
15
16pub fn encrypt_with_key(key: &[u8; 32], plaintext: &[u8]) -> Result<Vec<u8>, CryptoError> {
17 use rand::RngCore;
18
19 let cipher = Aes256Gcm::new_from_slice(key)
20 .map_err(|e| CryptoError::EncryptionFailed(format!("Failed to create cipher: {}", e)))?;
21
22 let mut nonce_bytes = [0u8; 12];
23 rand::thread_rng().fill_bytes(&mut nonce_bytes);
24
25 #[allow(deprecated)]
26 let nonce = Nonce::from_slice(&nonce_bytes);
27
28 let ciphertext = cipher
29 .encrypt(nonce, plaintext)
30 .map_err(|e| CryptoError::EncryptionFailed(format!("{}", e)))?;
31
32 let mut result = Vec::with_capacity(12 + ciphertext.len());
33 result.extend_from_slice(&nonce_bytes);
34 result.extend_from_slice(&ciphertext);
35
36 Ok(result)
37}
38
39pub fn decrypt_with_key(key: &[u8; 32], encrypted: &[u8]) -> Result<Vec<u8>, CryptoError> {
40 if encrypted.len() < 12 {
41 return Err(CryptoError::DecryptionFailed(
42 "Encrypted data too short".to_string(),
43 ));
44 }
45
46 let cipher = Aes256Gcm::new_from_slice(key)
47 .map_err(|e| CryptoError::DecryptionFailed(format!("Failed to create cipher: {}", e)))?;
48
49 #[allow(deprecated)]
50 let nonce = Nonce::from_slice(&encrypted[..12]);
51 let ciphertext = &encrypted[12..];
52
53 cipher
54 .decrypt(nonce, ciphertext)
55 .map_err(|e| CryptoError::DecryptionFailed(format!("{}", e)))
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_encrypt_decrypt() {
64 let key = [0u8; 32];
65 let plaintext = b"hello world";
66 let encrypted = encrypt_with_key(&key, plaintext).unwrap();
67 let decrypted = decrypt_with_key(&key, &encrypted).unwrap();
68 assert_eq!(plaintext.as_slice(), decrypted.as_slice());
69 }
70
71 #[test]
72 fn test_derive_key() {
73 let master = b"master-key-for-testing";
74 let key1 = derive_key(master, b"context-1").unwrap();
75 let key2 = derive_key(master, b"context-2").unwrap();
76 assert_ne!(key1, key2);
77 }
78}