use std::cmp::PartialEq;
use std::fmt::Debug;
use std::iter::repeat;
use std::thread;
use std::thread::JoinHandle;
use aes::Aes256Ctr;
use ctr::cipher::generic_array::GenericArray;
use base64;
use bcrypt::bcrypt;
use aes::cipher::{NewCipher, StreamCipher};
use hkdf::Hkdf;
use rand::{thread_rng, Rng, RngCore};
use sha2::Sha256;
use sha3::{Digest, Sha3_512};
use zeroize::Zeroize;
use super::errors::{self, RustKeylockError};
use super::protected::RklSecret;
const NUMBER_OF_SALT_KEY_PAIRS: usize = 10;
pub(crate) const BCRYPT_COST: u32 = 7;
pub trait Cryptor {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError>;
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError>;
}
#[derive(Debug, PartialEq)]
pub struct BcryptAes {
key: RklSecret,
iv: Vec<u8>,
salt_position: usize,
salt_key_pairs: Vec<(Vec<u8>, RklSecret)>,
hasher: Sha3Keccak512,
hash: RklSecret,
}
impl BcryptAes {
fn create_key(input: &[u8], salt: &[u8], cost: u32, output_bytes_size: i32) -> Vec<u8> {
let mut key: Vec<u8> = Vec::new();
let mut ikm: Vec<u8> = repeat(0u8).take(24).collect();
bcrypt(cost, &salt, input, &mut ikm);
let info = b"rust-keylock";
let hk = Hkdf::<Sha256>::new(Some(&salt), &ikm);
let mut okm: Vec<u8> = repeat(0u8).take(output_bytes_size as usize).collect();
hk.expand(info, &mut okm).unwrap();
key.append(&mut okm);
key
}
pub fn new(mut password: String,
mut salt: Vec<u8>,
iv: Vec<u8>,
mut salt_position: usize,
hash_bytes: Vec<u8>, )
-> BcryptAes {
let mut salt_key_pairs = Vec::new();
let handles: Vec<JoinHandle<(Vec<u8>, RklSecret)>> = (0..NUMBER_OF_SALT_KEY_PAIRS + 1)
.map(|i| {
let cp = password.clone();
let cs = salt.clone();
let child = thread::spawn(move || {
if i == 0 {
let key = BcryptAes::create_key(cp.as_bytes(), &cs, BCRYPT_COST, 64);
(cs, RklSecret::new(key))
} else {
let s = create_random(16);
let k = BcryptAes::create_key(cp.as_bytes(), &s, BCRYPT_COST, 64);
(s, RklSecret::new(k))
}
});
child
})
.collect();
for handle in handles {
salt_key_pairs.push(handle.join().unwrap());
}
let hasher = Sha3Keccak512::new();
let to_ret = BcryptAes {
key: salt_key_pairs.remove(0).1.clone(),
iv,
salt_position,
salt_key_pairs,
hasher,
hash: RklSecret::new(hash_bytes),
};
password.zeroize();
salt.zeroize();
salt_position.zeroize();
to_ret
}
fn decrypt_bytes(&self, encrypted: &[u8], key: &[u8]) -> errors::Result<Vec<u8>> {
let mut data: Vec<u8> = encrypted.to_vec();
let k = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(&self.iv);
let mut cipher = Aes256Ctr::new(&k, &nonce);
cipher.try_apply_keystream(&mut data)?;
Ok(data)
}
fn encrypt_bytes(&self, plain: &[u8], key: &[u8], iv: &[u8]) -> errors::Result<Vec<u8>> {
let mut data: Vec<u8> = plain.to_vec();
let k = GenericArray::from_slice(key);
let nonce = GenericArray::from_slice(iv);
let mut cipher = Aes256Ctr::new(&k, &nonce);
cipher.try_apply_keystream(&mut data)?;
Ok(data)
}
}
impl Cryptor for BcryptAes {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let bytes_to_decrypt = extract_bytes_to_decrypt(input, self.salt_position);
let legacy_handling = self.key.borrow().len() > 64;
let (final_result, integrity_check_ok) = if legacy_handling {
let key: Vec<u8> = self.key.borrow().iter()
.take(32)
.cloned()
.collect();
let integrity_check_ok = self.hasher.validate_hash(&bytes_to_decrypt, self.hash.borrow());
let final_result = self.decrypt_bytes(&bytes_to_decrypt, &key)?;
(final_result, integrity_check_ok)
} else {
let hash_decryption_key: Vec<u8> = self.key.borrow().iter()
.take(32)
.cloned()
.collect();
let data_decryption_key: Vec<u8> = self.key.borrow().iter()
.skip(32)
.take(32)
.cloned()
.collect();
let hash = self.decrypt_bytes(self.hash.borrow(), &hash_decryption_key)?;
let integrity_check_ok = self.hasher.validate_hash(&bytes_to_decrypt, &hash);
let final_result = self.decrypt_bytes(&bytes_to_decrypt, &data_decryption_key)?;
(final_result, integrity_check_ok)
};
if !integrity_check_ok {
Err(RustKeylockError::DecryptionError("".to_string()))
} else {
Ok(final_result)
}
}
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let iv = create_random(16);
let mut rng = thread_rng();
let idx = {
rng.gen_range(0.. NUMBER_OF_SALT_KEY_PAIRS)
};
let salt_key_pair = &self.salt_key_pairs[idx];
let hash_encryption_key: Vec<u8> = salt_key_pair.1.borrow().iter()
.take(32)
.cloned()
.collect();
let data_encryption_key: Vec<u8> = salt_key_pair.1.borrow().iter()
.skip(32)
.take(32)
.cloned()
.collect();
let encrypted_data_bytes = self.encrypt_bytes(input, &data_encryption_key, &iv)?;
let hash_bytes = self.hasher.calculate_hash(&encrypted_data_bytes);
let encrypted_hash_bytes = self.encrypt_bytes(&hash_bytes, &hash_encryption_key, &iv)?;
Ok(compose_bytes_to_save(&encrypted_data_bytes, self.salt_position, &salt_key_pair.0, &iv, &encrypted_hash_bytes))
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct EntryPasswordCryptor {
key: RklSecret,
iv: Vec<u8>,
}
impl Zeroize for EntryPasswordCryptor {
fn zeroize(&mut self) {
self.iv.zeroize();
}
}
impl EntryPasswordCryptor {
pub fn new() -> EntryPasswordCryptor {
let password = create_random(32);
let iv = create_random(16);
let salt = create_random(16);
let mut key: Vec<u8> = create_random(24);
bcrypt(3, &salt, &password, &mut key);
let append_to_key: Vec<u8> = repeat(0u8).take(8).collect();
key.extend(append_to_key.iter());
EntryPasswordCryptor {
key: RklSecret::new(key),
iv,
}
}
pub fn encrypt_str(&self, input: &str) -> Result<String, RustKeylockError> {
let encrypted = self.encrypt(input.as_bytes())?;
Ok(base64::encode(&encrypted))
}
pub fn decrypt_str(&self, input: &str) -> Result<String, RustKeylockError> {
let encrypted = base64::decode(&input)?;
let decrypted_bytes = self.decrypt(&encrypted)?;
Ok(String::from_utf8(decrypted_bytes)?)
}
}
impl Default for EntryPasswordCryptor {
fn default() -> Self {
Self::new()
}
}
impl Cryptor for EntryPasswordCryptor {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let mut data: Vec<u8> = input.to_vec();
let k = GenericArray::from_slice(&self.key.borrow());
let nonce = GenericArray::from_slice(&self.iv);
let mut cipher = Aes256Ctr::new(&k, &nonce);
cipher.try_apply_keystream(&mut data)?;
Ok(data)
}
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let mut data: Vec<u8> = input.to_vec();
let k = GenericArray::from_slice(&self.key.borrow());
let nonce = GenericArray::from_slice(&self.iv);
let mut cipher = Aes256Ctr::new(&k, &nonce);
cipher.try_apply_keystream(&mut data)?;
Ok(data)
}
}
#[allow(dead_code)]
pub struct NoCryptor;
impl NoCryptor {
#[allow(dead_code)]
pub fn new() -> NoCryptor {
NoCryptor {}
}
}
impl Default for NoCryptor {
fn default() -> Self {
Self::new()
}
}
impl Cryptor for NoCryptor {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
Ok(Vec::from(input))
}
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
Ok(Vec::from(input))
}
}
pub trait Hasher: Debug + PartialEq {
fn validate_hash(&self, data: &[u8], hash: &[u8]) -> bool;
fn calculate_hash(&self, data: &[u8]) -> Vec<u8>;
}
#[derive(Debug, PartialEq)]
pub struct Sha3Keccak512;
impl Sha3Keccak512 {
pub fn new() -> Sha3Keccak512 {
Sha3Keccak512
}
}
impl Default for Sha3Keccak512 {
fn default() -> Self {
Self::new()
}
}
impl Hasher for Sha3Keccak512 {
fn validate_hash(&self, data: &[u8], hash: &[u8]) -> bool {
let mut hasher = Sha3_512::default();
hasher.update(data);
let data_hash = hasher.finalize();
data_hash.as_slice() == hash
}
fn calculate_hash(&self, data: &[u8]) -> Vec<u8> {
let mut hasher = Sha3_512::default();
hasher.update(data);
let data_hash = hasher.finalize();
Vec::from(data_hash.as_slice())
}
}
pub fn create_random(size: usize) -> Vec<u8> {
let mut random: Vec<u8> = repeat(0u8).take(size).collect();
thread_rng().fill_bytes(&mut random);
random
}
pub fn create_random_utf_string(size: usize) -> String {
repeat(())
.map(|()| thread_rng().sample(rand::distributions::Alphanumeric))
.map(char::from)
.take(size)
.collect()
}
fn extract_bytes_to_decrypt(input_bytes: &[u8], salt_position: usize) -> Vec<u8> {
let bytes = Vec::from(input_bytes);
let salt_between_data = bytes.len() >= 96 && salt_position < (bytes.len() - 96);
let bytes_to_decrypt: Vec<u8> = bytes
.iter()
.skip(16)
.enumerate()
.filter(|tup| {
if salt_between_data {
tup.0 < salt_position || tup.0 >= salt_position + 80
} else {
tup.0 < bytes.len() - 96
}
})
.map(|tup| tup.1)
.cloned()
.collect();
bytes_to_decrypt
}
fn compose_bytes_to_save(data: &[u8], salt_position: usize, salt: &[u8], iv: &[u8], hash: &[u8]) -> Vec<u8> {
let mut bytes_to_save: Vec<u8> = Vec::new();
let mut mut_iv = Vec::from(iv);
let inferred_salt_position = {
if salt_position < data.len() {
salt_position
} else {
data.len()
}
};
let hash_position = inferred_salt_position + 16;
bytes_to_save.append(&mut mut_iv);
let length = data.len() + salt.len() + hash.len();
for index in 0..length {
if index < inferred_salt_position {
bytes_to_save.push(data[index]);
} else if index >= inferred_salt_position && index < inferred_salt_position + 16 {
bytes_to_save.push(salt[index - inferred_salt_position]);
} else if index >= hash_position && index < hash_position + 64 {
bytes_to_save.push(hash[index - hash_position]);
} else {
bytes_to_save.push(data[index - 80]);
}
}
bytes_to_save
}
#[cfg(test)]
mod test_crypt {
use super::{Cryptor, Hasher};
#[test]
fn create_random() {
let mut randoms = Vec::new();
for _ in 0..1000 {
let random = super::create_random(16);
assert!(random.len() == 16);
assert!(!randoms.contains(&random));
randoms.push(random);
}
}
#[test]
fn compose_bytes_to_save_salt_position_0() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 0;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let s: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(32).take(64).collect();
let d: Vec<u8> = vec.iter().cloned().skip(96).take(16).collect();
assert!(i == iv);
assert!(s == salt);
assert!(h == hash);
assert!(d == data);
}
#[test]
fn compose_bytes_to_save_salt_position_0_and_no_real_data() {
let data = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 0;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let s: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(32).take(64).collect();
let d: Vec<u8> = vec.iter().cloned().skip(96).take(16).collect();
assert!(i == iv);
assert!(s == salt);
assert!(h == hash);
assert!(d == data);
}
#[test]
fn compose_bytes_to_save_salt_position_smaller_than_data_length() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 3;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let mut d: Vec<u8> = vec.iter().cloned().skip(16).take(3).collect();
let mut d_rest: Vec<u8> = vec.iter().cloned().skip(99).take(13).collect();
d.append(&mut d_rest);
let s: Vec<u8> = vec.iter().cloned().skip(19).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(35).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(h == hash);
assert!(d == data);
}
#[test]
fn compose_bytes_to_save_salt_position_smaller_than_data_length_and_no_real_data() {
let data = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 3;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let s: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(32).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(h == hash);
}
#[test]
fn compose_bytes_to_save_salt_position_bigger_than_data_length() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 33;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let d: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let s: Vec<u8> = vec.iter().cloned().skip(32).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(48).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(d == data);
assert!(h == hash);
}
#[test]
fn compose_bytes_to_save_salt_position_bigger_than_data_length_no_real_data() {
let data = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 33;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let d: Vec<u8> = Vec::new();
let s: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(32).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(h == hash);
assert!(d == data);
}
#[test]
fn compose_bytes_to_save_salt_position_equal_to_data_length() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 16;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let d: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let s: Vec<u8> = vec.iter().cloned().skip(32).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(48).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(d == data);
assert!(h == hash);
}
#[test]
fn compose_bytes_to_save_salt_position_equal_to_data_length_no_real_data() {
let data = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let salt_position = 16;
let hash = super::Sha3Keccak512::new().calculate_hash(&data);
let vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &hash);
let i: Vec<u8> = vec.iter().cloned().take(16).collect();
let d: Vec<u8> = Vec::new();
let s: Vec<u8> = vec.iter().cloned().skip(16).take(16).collect();
let h: Vec<u8> = vec.iter().cloned().skip(32).take(64).collect();
assert!(i == iv);
assert!(s == salt);
assert!(d == data);
assert!(h == hash);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_0() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp: Vec<u8> = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = data.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 0;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_0_no_real_data() {
let data = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp: Vec<u8> = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = data.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 0;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_smaller_than_data_length() {
let data1 = vec![0x10u8, 0x11u8, 0x12u8];
let data2 = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8];
let mut data: Vec<u8> = data1.iter().cloned().collect();
let mut tmp: Vec<u8> = data2.iter().cloned().collect();
data.append(&mut tmp);
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
tmp = data1.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = data2.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 3;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_bigger_than_data_length() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp = data.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 33;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_bigger_than_data_length_no_real_data() {
let data: Vec<u8> = Vec::new();
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 33;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn extract_bytes_to_decrypt_salt_position_equal_to_data_length() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let salt = vec![0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8, 0x04u8, 0x10u8, 0x41u8,
0x04u8, 0x10u8];
let iv = vec![0x11u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8, 0x03u8, 0x10u8, 0x43u8,
0x03u8, 0x10u8];
let hash = super::create_random(64);
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp = data.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = hash.iter().cloned().collect();
bytes.append(&mut tmp);
let salt_position = 16;
let vec = super::extract_bytes_to_decrypt(&bytes, salt_position);
assert!(vec == data);
}
#[test]
fn password_encryption() {
let password_cryptor = super::EntryPasswordCryptor::new();
let password = "hello".as_bytes();
let encrypted_password = password_cryptor.encrypt(password);
assert!(encrypted_password.is_ok());
assert!(encrypted_password.as_ref().unwrap() != &password);
let decrypted_password = password_cryptor.decrypt(&encrypted_password.unwrap());
assert!(decrypted_password.is_ok());
assert!(decrypted_password.unwrap() == password);
}
#[test]
fn password_string_encryption() {
let password_cryptor = super::EntryPasswordCryptor::new();
let password = "hello";
let encrypted_password = password_cryptor.encrypt_str(&password);
assert!(encrypted_password.is_ok());
assert!(encrypted_password.as_ref().unwrap() != &password);
let decrypted_password = password_cryptor.decrypt_str(&encrypted_password.unwrap());
assert!(decrypted_password.is_ok());
assert!(decrypted_password.unwrap() == password);
}
#[test]
fn hash() {
let data = vec![0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8, 0x12u8, 0x10u8, 0x11u8,
0x12u8, 0x10u8];
let hasher = super::Sha3Keccak512::new();
let hash = hasher.calculate_hash(&data);
assert!(hash.len() == 64);
assert!(hasher.validate_hash(&data, &hash));
}
#[test]
fn integrity_failure_on_bcrypt_aes() {
let iv = super::create_random(16);
let salt = super::create_random(16);
let hash = super::create_random(64);
let data = b"This is the data";
let mut bytes: Vec<u8> = iv.iter().cloned().collect();
let mut tmp = salt.iter().cloned().collect();
bytes.append(&mut tmp);
tmp = super::create_random(64);
bytes.append(&mut tmp);
tmp = data.iter().cloned().collect();
bytes.append(&mut tmp);
let cryptor = super::BcryptAes::new("password".to_string(), salt, iv, 1, hash);
let result = cryptor.decrypt(&bytes);
assert!(result.is_err());
match result.err() {
Some(super::super::errors::RustKeylockError::DecryptionError(_)) => assert!(true),
_ => assert!(false),
}
}
#[test]
fn new_bcryptor_checks() {
let iv = super::create_random(16);
let salt = super::create_random(16);
let hash = super::create_random(64);
let cryptor = super::BcryptAes::new("password".to_string(), salt.clone(), iv, 1, hash);
assert!(cryptor.salt_key_pairs.len() == super::NUMBER_OF_SALT_KEY_PAIRS);
for skp in cryptor.salt_key_pairs {
assert!(&skp.0 != &salt);
assert!(&skp.1 != &cryptor.key);
}
}
#[test]
fn bcrypt_key_creation() {
let small_key = super::BcryptAes::create_key("123".as_bytes(), "saltsaltsaltsalt".as_bytes(), 3, 12);
assert!(small_key.len() == 12);
let key = super::BcryptAes::create_key("123".as_bytes(), "saltsaltsaltsalt".as_bytes(), 3, 32);
assert!(key.len() == 32);
let key: Vec<u8> = super::BcryptAes::create_key("123".as_bytes(), "saltsaltsaltsalt".as_bytes(), 3, 64);
for _ in 0..20 {
assert!(&super::BcryptAes::create_key("123".as_bytes(), "saltsaltsaltsalt".as_bytes(), 3, 64) == &key);
}
}
}