sentinel_crypto/encrypt/
aes_gcm_siv.rs1use aes_gcm_siv::{
2 aead::{Aead, KeyInit},
3 Aes256GcmSiv,
4 Key,
5 Nonce,
6};
7use rand::RngCore;
8
9use crate::{encrypt_trait::EncryptionAlgorithm, error::CryptoError};
10
11pub struct Aes256GcmSivEncryptor;
19
20impl EncryptionAlgorithm for Aes256GcmSivEncryptor {
21 fn encrypt_data(data: &[u8], key: &[u8; 32]) -> Result<String, CryptoError> {
22 let cipher = Aes256GcmSiv::new(Key::<Aes256GcmSiv>::from_slice(key));
23 let mut nonce_bytes = [0u8; 12];
24 rand::rng().fill_bytes(&mut nonce_bytes);
25 let nonce = Nonce::from_slice(&nonce_bytes);
26
27 let ciphertext = cipher
28 .encrypt(nonce, data)
29 .map_err(|_| CryptoError::Encryption)?;
30 let mut result = nonce_bytes.to_vec();
31 result.extend_from_slice(&ciphertext);
32 Ok(hex::encode(result))
33 }
34
35 fn decrypt_data(encrypted_data: &str, key: &[u8; 32]) -> Result<Vec<u8>, CryptoError> {
36 let data = hex::decode(encrypted_data).map_err(|_| CryptoError::Decryption)?;
37 if data.len() < 12 {
38 return Err(CryptoError::Decryption);
39 }
40 let (nonce_bytes, ciphertext) = data.split_at(12);
41 let cipher = Aes256GcmSiv::new(Key::<Aes256GcmSiv>::from_slice(key));
42 let nonce = Nonce::from_slice(nonce_bytes);
43 cipher
44 .decrypt(nonce, ciphertext)
45 .map_err(|_| CryptoError::Decryption)
46 }
47}
48
49impl crate::encrypt_trait::private::Sealed for Aes256GcmSivEncryptor {}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn test_encrypt_decrypt() {
57 let key = [0u8; 32];
58 let data = b"Hello, world!";
59 let encrypted = Aes256GcmSivEncryptor::encrypt_data(data, &key).unwrap();
60 let decrypted = Aes256GcmSivEncryptor::decrypt_data(&encrypted, &key).unwrap();
61 assert_eq!(decrypted, data);
62 }
63
64 #[test]
65 fn test_decrypt_invalid_length() {
66 let key = [0u8; 32];
67 let short_hex = hex::encode(&[0u8; 10]); let result = Aes256GcmSivEncryptor::decrypt_data(&short_hex, &key);
70 assert!(result.is_err());
71 }
72}