use std::borrow::Borrow;
use crate::version1::{
Result,
};
use pkcs5::{
EncryptionScheme,
pbes2::Parameters as PBES2Parameters,
};
use scrypt::Params as ScryptParams;
use aes_gcm_siv::{
Aes256GcmSiv, Aes128GcmSiv, Nonce, Key,
aead::{Aead, NewAead},
};
use byteorder::{LittleEndian, WriteBytesExt};
use rand::{rngs::OsRng, RngCore};
#[repr(u8)]
#[non_exhaustive]
#[derive(Debug,Clone,Eq,PartialEq)]
pub enum EncryptionAlgorithm {
AES128GCMSIV = 0,
AES256GCMSIV = 1,
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Debug,Clone,Eq,PartialEq)]
pub enum KDFScheme {
PBKDF2SHA256 = 0,
Scrypt = 1,
}
#[repr(u8)]
#[non_exhaustive]
#[derive(Debug,Clone,Eq,PartialEq)]
pub enum PBEScheme {
AES128CBC = 0,
AES256CBC = 1,
}
pub struct Encryption;
impl Encryption {
pub fn encrypt_pbkdf2sha256_aes128cbc(
iterations: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::pbkdf2_sha256_aes128cbc(iterations, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.encrypt(password, plaintext)?)
}
pub fn encrypt_pbkdf2sha256_aes256cbc(
iterations: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::pbkdf2_sha256_aes256cbc(iterations, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
let cipher = encryption_scheme.encrypt(password, plaintext)?;
Ok(cipher)
}
pub fn decrypt_pbkdf2sha256_aes128cbc(
iterations: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
ciphertext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::pbkdf2_sha256_aes128cbc(iterations, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.decrypt(password, ciphertext)?)
}
pub fn decrypt_pbkdf2sha256_aes256cbc(
iterations: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
ciphertext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::pbkdf2_sha256_aes256cbc(iterations, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.decrypt(password, ciphertext)?)
}
pub fn encrypt_scrypt_aes128cbc(
logn: u8,
r: u32,
p: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::scrypt_aes128cbc(ScryptParams::new(logn, r, p)?, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.encrypt(password, plaintext)?)
}
pub fn encrypt_scrypt_aes256cbc(
logn: u8,
r: u32,
p: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::scrypt_aes256cbc(ScryptParams::new(logn, r, p)?, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.encrypt(password, plaintext)?)
}
pub fn decrypt_scrypt_aes128cbc(
logn: u8,
r: u32,
p: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::scrypt_aes128cbc(ScryptParams::new(logn, r, p)?, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.decrypt(password, plaintext)?)
}
pub fn decrypt_scrypt_aes256cbc(
logn: u8,
r: u32,
p: u32,
salt: &[u8; 32],
aes_iv: &[u8; 16],
password: impl AsRef<[u8]>,
plaintext: &[u8]) -> Result<Vec<u8>> {
let params = PBES2Parameters::scrypt_aes256cbc(ScryptParams::new(logn, r, p)?, salt, aes_iv)?;
let encryption_scheme = EncryptionScheme::Pbes2(params);
Ok(encryption_scheme.decrypt(password, plaintext)?)
}
pub fn encrypt_message<K, M, A>(key: K, message: M, chunk_no: u64, algorithm: A) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
M: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
let nonce = Encryption::chunk_as_crypto_nonce(chunk_no)?;
match algorithm.borrow() {
EncryptionAlgorithm::AES256GCMSIV => {
let cipher = Aes256GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.encrypt(&nonce, message.as_ref())?)
},
EncryptionAlgorithm::AES128GCMSIV => {
let cipher = Aes128GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.encrypt(&nonce, message.as_ref())?)
},
}
}
pub fn decrypt_message<K, M, A>(key: K, message: M, chunk_no: u64, algorithm: A) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
M: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
let nonce = Encryption::chunk_as_crypto_nonce(chunk_no)?;
match algorithm.borrow() {
EncryptionAlgorithm::AES256GCMSIV => {
let cipher = Aes256GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.decrypt(&nonce, message.as_ref())?)
},
EncryptionAlgorithm::AES128GCMSIV => {
let cipher = Aes128GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.decrypt(&nonce, message.as_ref())?)
},
}
}
pub(crate) fn encrypt_header<K, M, A>(key: K, message: M, nonce: &[u8; 12], algorithm: A) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
M: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
let nonce = Nonce::from_slice(nonce);
match algorithm.borrow() {
EncryptionAlgorithm::AES256GCMSIV => {
let cipher = Aes256GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.encrypt(nonce, message.as_ref())?)
},
EncryptionAlgorithm::AES128GCMSIV => {
let cipher = Aes128GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.encrypt(nonce, message.as_ref())?)
},
}
}
pub(crate) fn decrypt_header<K, C, A>(key: K, ciphertext: C, nonce: &[u8; 12], algorithm: A) -> Result<Vec<u8>>
where
K: AsRef<[u8]>,
C: AsRef<[u8]>,
A: Borrow<EncryptionAlgorithm>,
{
let nonce = Nonce::from_slice(nonce);
match *algorithm.borrow() {
EncryptionAlgorithm::AES256GCMSIV => {
let cipher = Aes256GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.decrypt(nonce, ciphertext.as_ref())?)
},
EncryptionAlgorithm::AES128GCMSIV => {
let cipher = Aes128GcmSiv::new(Key::from_slice(key.as_ref()));
Ok(cipher.decrypt(nonce, ciphertext.as_ref())?)
},
}
}
pub fn gen_random_key(length: usize) -> Vec<u8> {
let mut key = vec!(0u8; length/8);
let mut rng = OsRng;
rng.fill_bytes(&mut key);
key
}
pub fn gen_random_iv() -> [u8; 16] {
let mut iv = [0; 16];
let mut rng = OsRng;
rng.fill_bytes(&mut iv);
iv
}
pub fn gen_random_salt() -> [u8; 32] {
let mut salt = [0; 32];
let mut rng = OsRng;
rng.fill_bytes(&mut salt);
salt
}
pub fn gen_random_header_nonce() -> [u8; 12] {
let mut nonce = [0; 12];
let mut rng = OsRng;
rng.fill_bytes(&mut nonce);
nonce
}
fn chunk_as_crypto_nonce(chunk_no: u64) -> Result<Nonce> {
let mut buffer = vec![];
buffer.write_u64::<LittleEndian>(chunk_no)?;
buffer.append(&mut vec!(0u8; 4));
Ok(*Nonce::from_slice(&buffer))
}
}