use aes_gcm::{
aead::{generic_array::GenericArray, Aead, Error as AeadError},
Aes256Gcm,
};
use rand::{rngs::OsRng, RngCore};
pub const AES_NONCE_BYTES: usize = 12;
pub const AES_KEY_BYTES: usize = 32;
pub trait Encryptable<C> {
fn encrypt(&mut self, cipher: &C) -> Result<(), AeadError>;
fn decrypt(&mut self, cipher: &C) -> Result<(), AeadError>;
}
pub fn decrypt_bytes_integral_nonce(cipher: &Aes256Gcm, ciphertext: Vec<u8>) -> Result<Vec<u8>, AeadError> {
if ciphertext.len() < AES_NONCE_BYTES {
return Err(AeadError);
}
let (nonce, cipher_text) = ciphertext.split_at(AES_NONCE_BYTES);
let nonce = GenericArray::from_slice(nonce);
cipher.decrypt(nonce, cipher_text.as_ref())
}
pub fn encrypt_bytes_integral_nonce(cipher: &Aes256Gcm, plaintext: Vec<u8>) -> Result<Vec<u8>, AeadError> {
let mut nonce = [0u8; AES_NONCE_BYTES];
OsRng.fill_bytes(&mut nonce);
let nonce_ga = GenericArray::from_slice(&nonce);
let mut ciphertext = cipher.encrypt(nonce_ga, plaintext.as_ref())?;
let mut ciphertext_integral_nonce = nonce.to_vec();
ciphertext_integral_nonce.append(&mut ciphertext);
Ok(ciphertext_integral_nonce)
}
#[cfg(test)]
mod test {
use crate::util::encryption::{decrypt_bytes_integral_nonce, encrypt_bytes_integral_nonce};
use aes_gcm::{
aead::{generic_array::GenericArray, NewAead},
Aes256Gcm,
};
#[test]
fn test_encrypt_decrypt() {
let plaintext = b"The quick brown fox was annoying".to_vec();
let key = GenericArray::from_slice(b"an example very very secret key.");
let cipher = Aes256Gcm::new(key);
let cipher_text = encrypt_bytes_integral_nonce(&cipher, plaintext.clone()).unwrap();
let decrypted_text = decrypt_bytes_integral_nonce(&cipher, cipher_text).unwrap();
assert_eq!(decrypted_text, plaintext);
}
}