use aes_gcm::{
aead::{Aead, KeyInit, OsRng},
Aes256Gcm, Key, Nonce,
};
use rand::RngCore;
use crate::crypto::primitives::EncValue;
use crate::error::VaultError;
const NONCE_LEN: usize = 12;
pub fn encrypt(key: &[u8; 32], plaintext: &[u8]) -> Result<EncValue, VaultError> {
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let mut nonce_bytes = [0u8; NONCE_LEN];
OsRng.fill_bytes(&mut nonce_bytes);
let nonce = Nonce::from_slice(&nonce_bytes);
let ciphertext = cipher
.encrypt(nonce, plaintext)
.map_err(|_| VaultError::Crypto("AES-GCM encrypt failed".into()))?;
let mut out = Vec::with_capacity(NONCE_LEN + ciphertext.len());
out.extend_from_slice(&nonce_bytes);
out.extend_from_slice(&ciphertext);
Ok(EncValue(out))
}
pub fn decrypt(key: &[u8; 32], value: &EncValue) -> Result<Vec<u8>, VaultError> {
let bytes = &value.0;
if bytes.len() < NONCE_LEN + 16 {
return Err(VaultError::Crypto("EncValue too short".into()));
}
let (nonce_bytes, ciphertext) = bytes.split_at(NONCE_LEN);
let cipher = Aes256Gcm::new(Key::<Aes256Gcm>::from_slice(key));
let nonce = Nonce::from_slice(nonce_bytes);
cipher
.decrypt(nonce, ciphertext)
.map_err(|_| VaultError::Tampered)
}