squaredb_enc 1.0.0-beta

Squaredb - Enhance your DB with extendability and performance.
Documentation
use crate::err::EncryptionError;
use aes_gcm::Aes256Gcm;
use aes_gcm::aead:: {
  Aead,
  generic_array::GenericArray
};
use aes_gcm::KeyInit;
use rand:: {
  Rng,
  thread_rng
};
use crate::pbkdf::PBKDF;
use crate::pbkdf::KeyDerivation;
use crate::NONCE_SIZE;

#[derive(Clone)]
pub struct AesEncryptor {
  cipher: Aes256Gcm,
}

pub trait Encryptor {
  fn new(password: &str) -> Result<Self,
  EncryptionError>
  where
  Self: Sized;

  fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>,
  EncryptionError>;
  
  fn random_nonce() -> Vec<u8>;
  
  fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>,
  EncryptionError>;
}

impl Encryptor for AesEncryptor {
  fn new(password: &str) -> Result<Self,
  EncryptionError> {
    let kdfp = PBKDF::new(password.to_string())?;
    let key = GenericArray::from_slice(&kdfp);
    let cipher = Aes256Gcm::new(key);
    Ok(AesEncryptor {
      cipher
    })
  }

  fn random_nonce() -> Vec<u8> {
    let mut rng = thread_rng();
    let mut vec = Vec::with_capacity(NONCE_SIZE);
    for _ in 0..NONCE_SIZE {
      vec.push(rng.gen::<u8>());
    }
    vec
  }

  fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>,
  EncryptionError> {
    let binding = Self::random_nonce();
    let nonce = GenericArray::from_slice(&binding); // 96-bits; unique per message
    let ciphertext = self.cipher.encrypt(nonce, data.as_ref())
    .map_err(|err| EncryptionError::EncryptionFailed(err.to_string()));

    let mut encrypted_data = Vec::with_capacity(nonce.len() + ciphertext.clone()?.len());
    encrypted_data.extend_from_slice(&nonce);
    encrypted_data.extend_from_slice(&ciphertext?);
    Ok(encrypted_data)
  }

  fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>,
  EncryptionError> {
    let nonce = GenericArray::from_slice(&data[0..NONCE_SIZE]);
    self.cipher.decrypt(nonce, data[NONCE_SIZE..].as_ref())
    .map_err(|err| EncryptionError::DecryptionFailed(err.to_string()))
  }
}