use rand::{Rng, OsRng};
use std::iter::repeat;
use std::fmt::Debug;
use std::cmp::PartialEq;
use crypto::bcrypt::bcrypt;
use crypto::{buffer, aes, aessafe};
use crypto::blockmodes::CtrModeX8;
use crypto::aes::KeySize;
use crypto::buffer::{ReadBuffer, WriteBuffer, BufferResult};
use crypto::symmetriccipher::{Encryptor, Decryptor, SynchronousStreamCipher};
use super::errors::RustKeylockError;
use base64;
use super::protected::RklSecret;
use sha3::{Digest, Sha3_512};
const NUMBER_OF_SALT_KEY_PAIRS: usize = 10;
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_new_bcrypt_key(password: &str, salt: &[u8], cost: u32) -> Vec<u8> {
let mut key: Vec<u8> = repeat(0u8).take(24).collect();
bcrypt(cost, &salt, password.as_bytes(), &mut key);
key
}
pub fn new(password: String, salt: Vec<u8>, cost: u32, iv: Vec<u8>, salt_position: usize, hash_bytes: Vec<u8>) -> BcryptAes {
let key = BcryptAes::create_new_bcrypt_key(&password, &salt, cost);
let mut salt_key_pairs = Vec::new();
for _ in 0..NUMBER_OF_SALT_KEY_PAIRS {
let s = create_random(16);
let k = BcryptAes::create_new_bcrypt_key(&password, &s, cost);
salt_key_pairs.push((s, RklSecret::new(k)));
}
let hasher = Sha3Keccak512::new();
BcryptAes {
key: RklSecret::new(key),
iv: iv,
salt_position: salt_position,
salt_key_pairs: salt_key_pairs,
hasher: hasher,
hash: RklSecret::new(hash_bytes),
}
}
pub fn ctr(key_size: KeySize, key: &[u8], iv: &[u8]) -> Box<SynchronousStreamCipher + 'static> {
match key_size {
KeySize::KeySize128 => {
let aes_dec = aessafe::AesSafe128EncryptorX8::new(key);
let dec = Box::new(CtrModeX8::new(aes_dec, iv));
dec
}
KeySize::KeySize192 => {
let aes_dec = aessafe::AesSafe192EncryptorX8::new(key);
let dec = Box::new(CtrModeX8::new(aes_dec, iv));
dec
}
KeySize::KeySize256 => {
let aes_dec = aessafe::AesSafe256EncryptorX8::new(key);
let dec = Box::new(CtrModeX8::new(aes_dec, iv));
dec
}
}
}
}
impl Cryptor for BcryptAes {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let extracted_bytes = extract_bytes_to_decrypt(input, self.salt_position);
let integrity_check_ok = self.hasher.validate_hash(&extracted_bytes, &self.hash.borrow());
let bytes_to_decrypt = if integrity_check_ok {
debug!("Integrity check ok!");
extracted_bytes
} else {
warn!("Integrity check failed! Falling back to v0.2.1 handling...");
extract_bytes_to_decrypt_fallback_for_v_0_3_0_upgrade(input, self.salt_position)
};
let mut final_result = Vec::<u8>::new();
{
let mut decryptor = Self::ctr(aes::KeySize::KeySize256, &self.key.borrow(), &self.iv);
let mut read_buffer = buffer::RefReadBuffer::new(&bytes_to_decrypt);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
}
if !integrity_check_ok {
debug!("Returning an IntegrityError...");
Err(RustKeylockError::IntegrityError(final_result))
} else {
Ok(final_result)
}
}
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let iv = create_random(16);
let idx = {
let mut rng = OsRng::new().ok().unwrap();
rng.gen_range::<usize>(0, NUMBER_OF_SALT_KEY_PAIRS)
};
let ref salt_key_pair = self.salt_key_pairs[idx];
let bytes_to_save = {
let mut encryptor = Self::ctr(aes::KeySize::KeySize256, &salt_key_pair.1.borrow(), &iv);
let mut encryption_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(input);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result = try!(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true));
encryption_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
compose_bytes_to_save(&encryption_result, self.salt_position, &salt_key_pair.0, &iv, &self.hasher)
};
Ok(bytes_to_save)
}
}
pub struct EntryPasswordCryptor {
key: RklSecret,
iv: Vec<u8>,
}
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> = repeat(0u8).take(24).collect();
bcrypt(3, &salt, &password, &mut key);
EntryPasswordCryptor {
key: RklSecret::new(key),
iv: iv,
}
}
pub fn encrypt_str(&self, input: &str) -> Result<String, RustKeylockError> {
let encrypted = try!(self.encrypt(input.as_bytes()));
Ok(base64::encode(&encrypted))
}
pub fn decrypt_str(&self, input: &str) -> Result<String, RustKeylockError> {
let encrypted = try!(base64::decode(&input));
let decrypted_bytes = try!(self.decrypt(&encrypted));
Ok(try!(String::from_utf8(decrypted_bytes)))
}
}
impl Cryptor for EntryPasswordCryptor {
fn decrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let mut final_result = Vec::<u8>::new();
{
let mut decryptor = aes::ctr(aes::KeySize::KeySize256, &self.key.borrow(), &self.iv);
let mut read_buffer = buffer::RefReadBuffer::new(input);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
}
Ok(final_result)
}
fn encrypt(&self, input: &[u8]) -> Result<Vec<u8>, RustKeylockError> {
let mut encryptor = aes::ctr(aes::KeySize::KeySize256, &self.key.borrow(), &self.iv);
let mut encryption_result = Vec::<u8>::new();
let mut read_buffer = buffer::RefReadBuffer::new(input);
let mut buffer = [0; 4096];
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
loop {
let result = try!(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true));
encryption_result.extend(write_buffer.take_read_buffer().take_remaining().iter().cloned());
match result {
BufferResult::BufferUnderflow => break,
BufferResult::BufferOverflow => {}
}
}
Ok(encryption_result)
}
}
#[allow(dead_code)]
pub struct NoCryptor;
impl NoCryptor {
#[allow(dead_code)]
pub fn new() -> NoCryptor {
NoCryptor {}
}
}
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 Hasher for Sha3Keccak512 {
fn validate_hash(&self, data: &[u8], hash: &[u8]) -> bool {
let mut hasher = Sha3_512::default();
hasher.input(data);
let data_hash = hasher.result();
data_hash.as_slice() == hash
}
fn calculate_hash(&self, data: &[u8]) -> Vec<u8> {
let mut hasher = Sha3_512::default();
hasher.input(data);
let data_hash = hasher.result();
Vec::from(data_hash.as_slice())
}
}
pub fn create_random(size: usize) -> Vec<u8> {
let mut random: Vec<u8> = repeat(0u8).take(size).collect();
let mut rng = OsRng::new().ok().unwrap();
rng.fill_bytes(&mut random);
random
}
#[allow(unused_assignments)]
fn extract_bytes_to_decrypt(input_bytes: &[u8], salt_position: usize) -> Vec<u8> {
let bytes = if input_bytes.len() < 96 {
let bytes_to_add = create_random(96 - input_bytes.len());
let mut input_vec = Vec::new();
let mut vec_to_add = Vec::from(bytes_to_add);
input_vec = Vec::from(input_bytes);
input_vec.append(&mut vec_to_add);
input_vec
} else {
Vec::from(input_bytes)
};
let salt_between_data = 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.clone())
.collect();
bytes_to_decrypt
}
fn extract_bytes_to_decrypt_fallback_for_v_0_3_0_upgrade(bytes: &[u8], salt_position: usize) -> Vec<u8> {
let salt_between_data = salt_position < (bytes.len() - 32);
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 + 16
} else {
tup.0 < bytes.len() - 32
}
})
.map(|tup| tup.1.clone())
.collect();
bytes_to_decrypt
}
fn compose_bytes_to_save(data: &[u8], salt_position: usize, salt: &[u8], iv: &[u8], hasher: &Sha3Keccak512) -> Vec<u8> {
let mut bytes_to_save: Vec<u8> = Vec::new();
let hash_bytes = hasher.calculate_hash(data);
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_bytes.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_bytes[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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
}
#[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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
}
#[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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
}
#[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 vec = super::compose_bytes_to_save(&data, salt_position, &salt, &iv, &super::Sha3Keccak512::new());
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 == super::Sha3Keccak512::new().calculate_hash(&data));
}
#[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::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(), iv, 1, salt, 33, hash);
let result = cryptor.decrypt(&bytes);
assert!(result.is_err());
match result.err() {
Some(super::super::errors::RustKeylockError::IntegrityError(_)) => assert!(true),
_ => assert!(false),
}
}
}