pub use aes_gcm::{
aead::{generic_array::GenericArray, rand_core::RngCore, AeadInPlace, KeyInit, OsRng},
Aes128Gcm, Aes256Gcm, Nonce,
};
use zeroize::Zeroize;
pub type Result<T> = core::result::Result<T, EncryptionErrors>;
pub type AesGcm128Enc = EncAlgo<Aes128Gcm>;
pub type AesGcm256Enc = EncAlgo<Aes256Gcm>;
pub const AES_GCM_NONCE_SIZE: usize = 12;
pub const AES_GCM_TAG_SIZE: usize = 16;
#[derive(Debug)]
pub enum EncryptionErrors {
FailedEncrypt,
FailedDecrypt,
IncorrectPassword,
}
#[derive(Debug, PartialEq, Eq)]
pub enum Algo {
Aes128,
Aes256,
}
impl From<&str> for Algo {
fn from(v: &str) -> Self {
match v {
"aes256" => Algo::Aes256,
_ => Algo::Aes128,
}
}
}
impl From<u8> for Algo {
fn from(v: u8) -> Self {
match v {
1 => Algo::Aes256,
_ => Algo::Aes128
}
}
}
macro_rules! create_aes_gcm_encryptor {
($key:expr, $aesgcm:ident) => {{
let arr_key = GenericArray::from_slice($key);
$aesgcm::new(arr_key)
}};
}
pub trait EncryptorBase<CiAlgo>
where
CiAlgo: AeadInPlace,
{
fn encrypt(&mut self, data: &[u8]) -> Result<Vec<u8>> {
let mut encrypted_data = data.to_vec();
self.encrypt_in_place(&mut encrypted_data)?;
Ok(encrypted_data.to_vec())
}
fn decrypt(&mut self, data: &[u8], nonce: &[u8]) -> Result<Vec<u8>> {
let mut decrypted_data = data.to_vec();
self.decrypt_in_place(&mut decrypted_data, nonce)?;
Ok(decrypted_data.to_vec())
}
fn encrypt_in_place(&mut self, data: &mut Vec<u8>) -> Result<()> {
let mut nonce = vec![0; AES_GCM_NONCE_SIZE];
OsRng.fill_bytes(&mut nonce);
if self.get_encryptor().encrypt_in_place(Nonce::from_slice(&nonce), b"", data).is_err() {
return Err(EncryptionErrors::FailedEncrypt);
}
data.append(&mut nonce);
Ok(())
}
fn decrypt_in_place(&mut self, data: &mut Vec<u8>, nonce: &[u8]) -> Result<()> {
let nonce = Nonce::from_slice(nonce);
if self.get_encryptor().decrypt_in_place(nonce, b"", data).is_err() {
return Err(EncryptionErrors::FailedDecrypt);
}
Ok(())
}
fn get_encryptor(&self) -> &CiAlgo;
}
pub struct EncAlgo<T> {
encryptor: T,
}
impl<T> EncAlgo<T> {
pub fn new(key: &[u8], encryptor_func: fn(&[u8]) -> T) -> Self {
EncAlgo {
encryptor: encryptor_func(key),
}
}
}
pub fn create_128_encryptor(key: &[u8]) -> Aes128Gcm {
create_aes_gcm_encryptor!(&key[..16], Aes128Gcm)
}
pub fn create_256_encryptor(key: &[u8]) -> Aes256Gcm {
create_aes_gcm_encryptor!(&key[..32], Aes256Gcm)
}
impl<CiAlgo> EncryptorBase<CiAlgo> for EncAlgo<CiAlgo>
where
CiAlgo: AeadInPlace,
{
fn get_encryptor(&self) -> &CiAlgo {
&self.encryptor
}
}
pub struct SData<T: Zeroize>(pub T);
impl<T: Zeroize> Drop for SData<T> {
fn drop(&mut self) {
self.0.zeroize();
}
}