pub use crate::aescbc::kd::pbkdf2_sha384_128bits;
pub use crate::aescbc::kd::pbkdf2_sha384_256bits;
pub use crate::aescbc::kd::pbkdf2_sha512;
pub use crate::aescbc::kd::DerivationScheme;
pub use crate::aescbc::pad::Ansix923;
pub use crate::aescbc::pad::Padder128;
pub use crate::aescbc::pad::Padding;
pub use crate::aescbc::tp::{B128, B256};
pub use crate::errors::Error;
pub use crate::hashis::gcrc128;
pub use crate::hashis::gcrc256;
pub use crate::ioutils::{absolute_path, open_write, read_bytes, read_bytes_high_water_mark};
use hex;
use rand::prelude::*;
use aes::cipher::{
generic_array::GenericArray,
BlockDecrypt,
BlockEncrypt,
KeyInit,
};
use aes::Aes256;
use chrono::{DateTime, Utc};
use std::io::Write;
use std::path::Path;
pub trait EncryptionEngine {
fn encrypt_block(&self, plaintext: &[u8], xor_block: &[u8]) -> Vec<u8>;
fn decrypt_block(&self, ciphertext: &[u8], xor_block: &[u8]) -> Vec<u8>;
fn encrypt_blocks(&self, plaintext: &[u8]) -> Vec<u8>;
fn decrypt_blocks(&self, ciphertext: &[u8]) -> Vec<u8>;
}
pub fn xor_128(left: B128, right: B128) -> B128 {
let mut result: B128 = [0; 16];
for (i, (s, o)) in left.into_iter().zip(right.iter()).enumerate() {
result[i] = s ^ o;
}
result
}
pub fn xor_256(left: B256, right: B256) -> B256 {
let mut result: B256 = [0; 32];
for (i, (s, o)) in left.into_iter().zip(right.iter()).enumerate() {
result[i] = s ^ o;
}
result
}
pub fn xor(a: &[u8], b: &[u8]) -> Vec<u8> {
a.into_iter().zip(b.iter()).map(|(a, b)| a ^ b).collect()
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct FsMetadata {
mode: u8,
birthat: DateTime<Utc>,
accessat: DateTime<Utc>,
changeat: DateTime<Utc>,
modifyat: DateTime<Utc>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct SourceMeta {
filename: Option<String>,
stat: Option<FsMetadata>,
crc32: Option<String>,
md5sum: Option<String>,
sha1sum: Option<String>,
sha224sum: Option<String>,
sha256sum: Option<String>,
sha384sum: Option<String>,
sha512sum: Option<String>,
sha3_224sum: Option<String>,
sha3_256sum: Option<String>,
sha3_384sum: Option<String>,
sha3_512sum: Option<String>,
sha3sum: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize)]
pub struct Aes256Key {
version: String,
cycles: Option<u32>,
key: String,
iv: String,
blob: String,
sourcemeta: Option<SourceMeta>,
}
const AESMGPF: [u8; 8] = [0x1f, 0x8b, 0x08, 0x08, 0x61, 0x58, 0x37, 0x65];
fn getcurrentversion() -> String {
format!("obg-v{}", env!("CARGO_PKG_VERSION"))
}
pub fn match_prefix(magicpfx: &[u8]) -> bool {
magicpfx.to_vec() == AESMGPF.to_vec()
}
impl Aes256Key {
pub fn skey(&self) -> B256 {
let mut skey: B256 = [0x0; 32];
skey.copy_from_slice(&self.key.as_bytes()[..32]);
skey
}
pub fn siv(&self) -> B128 {
let mut siv: B128 = [0x0; 16];
siv.copy_from_slice(&self.iv.as_bytes()[..16]);
siv
}
pub fn with_sourcemeta(&self, meta: SourceMeta) -> Aes256Key {
let mut result = self.clone();
result.sourcemeta = Some(meta);
result
}
pub fn new(key: B256, iv: B128, blob: &[u8], cycles: u32) -> Aes256Key {
Aes256Key {
key: hex::encode(key),
iv: hex::encode(iv),
blob: hex::encode(blob),
cycles: Some(cycles),
sourcemeta: None,
version: getcurrentversion(),
}
}
pub fn new_with_meta(
key: B256,
iv: B128,
blob: &[u8],
cycles: u32,
meta: SourceMeta,
) -> Aes256Key {
Aes256Key {
key: hex::encode(key),
iv: hex::encode(iv),
blob: hex::encode(blob),
cycles: Some(cycles),
sourcemeta: Some(meta),
version: getcurrentversion(),
}
}
pub fn derive(
passwords: Vec<String>,
password_hwm: u64,
salts: Vec<String>,
salt_hwm: u64,
cycles: u32,
salt_derivation_scheme: DerivationScheme,
shuffle_iv: bool,
) -> Result<Aes256Key, Error> {
let mut rng = rand::thread_rng();
let mut password = Vec::<u8>::new();
for sec in passwords {
password.extend(if Path::new(&sec).exists() {
read_bytes_high_water_mark(&sec, password_hwm)?
} else {
sec.as_str().as_bytes().to_vec()
});
}
let mut salt = Vec::<u8>::new();
for st in salts {
salt.extend(if Path::new(&st).exists() {
read_bytes_high_water_mark(&st, salt_hwm)?
} else {
st.as_str().as_bytes().to_vec()
});
}
let key = pbkdf2_sha384_256bits(&password, &salt, cycles);
let blob = pbkdf2_sha512(&password, &salt, cycles, 72);
let dv = salt_derivation_scheme.derive(&salt, &password, cycles);
let mut iv = [0; 16];
iv.copy_from_slice(&dv[..16]);
if shuffle_iv {
iv.shuffle(&mut rng);
}
Ok(Aes256Key::new(key, iv, &blob, cycles))
}
pub fn save_to_yaml_file(&self, filename: String) -> Result<(), Error> {
let mut file = open_write(&filename)?;
let yaml = serde_yaml::to_string(self)?;
Ok(file.write_all(yaml.as_bytes())?)
}
pub fn load_from_yaml_file(filename: String) -> Result<Aes256Key, Error> {
let bytes = read_bytes(&filename)?;
let key: Aes256Key = serde_yaml::from_slice(&bytes)?;
Ok(key)
}
pub fn load_from_file(
filename: String,
strict: bool,
key_offset: Option<usize>,
salt_offset: Option<usize>,
blob_offset: Option<usize>,
moo: bool,
) -> Result<Aes256Key, Error> {
let bytes = read_bytes(&filename)?;
let mut ml: usize = 110;
ml = match key_offset {
Some(o) => {
if o > ml {
o
} else {
ml
}
}
None => ml,
};
ml = match salt_offset {
Some(o) => {
if o > ml {
o
} else {
ml
}
}
None => ml,
};
ml = match blob_offset {
Some(o) => {
if o > ml {
o
} else {
ml
}
}
None => ml,
};
if match moo {
true => bytes.len() / 2,
false => bytes.len(),
} < ml
{
return Err(Error::FileSystemError(format!(
"{} is too small for the set of constraints",
filename
)));
}
let mut bytes = bytes.to_vec();
if strict {
let mag1cpfx = bytes.drain(0..8).collect::<Vec<u8>>();
assert!(match_prefix(&mag1cpfx));
}
let lhs = (match moo {
true => bytes.len() / 2,
false => bytes.len(),
}) - 8
- match key_offset {
Some(o) => o,
None => 0,
};
let rhs = match moo {
true => bytes.len() / 2,
false => bytes.len(),
};
let iv = bytes.drain(lhs..rhs).collect::<Vec<u8>>();
let lhs = (match moo {
true => bytes.len() / 2,
false => bytes.len(),
}) - 16
- match salt_offset {
Some(o) => o,
None => 0,
};
let rhs = match moo {
true => bytes.len() / 2,
false => bytes.len(),
};
let key = bytes.drain(lhs..rhs).collect::<Vec<u8>>();
let lhs = (match moo {
true => bytes.len() / 2,
false => bytes.len(),
}) - 72
- match blob_offset {
Some(o) => o,
None => 0,
};
let rhs = match moo {
true => bytes.len() / 2,
false => bytes.len(),
};
let blob = bytes.drain(lhs..rhs).collect::<Vec<u8>>();
Ok(Aes256Key {
version: getcurrentversion(),
key: hex::encode(key),
blob: hex::encode(blob),
iv: hex::encode(iv),
cycles: None,
sourcemeta: None,
})
}
pub fn save_to_file(&self, filename: String) -> Result<(), Error> {
let mut file = open_write(&filename)?;
file.write_all(&AESMGPF.to_vec())?;
file.write_all(filename.as_str().as_bytes())?;
file.write_all(&[0x00, 0x00, 0x00, 0x00])?;
let mut rng = thread_rng();
let mut mods: Vec<usize> = (237..1283).collect();
mods.shuffle(&mut rng);
let len = mods[0];
let mut buf = Vec::<u8>::new();
buf.resize(len, 0xa);
rng.fill_bytes(&mut buf);
file.write_all(&buf)?;
file.write_all(&[
0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
])?; file.write_all(&hex::decode("0105161050110a12")?)?;
file.write_all(&[0x26, 0x7b, 0xfe, 0x0e])?;
file.write_all(&hex::decode(&format!(
"{:016x}",
match self.cycles {
Some(c) => c,
None => 0,
}
))?)?;
file.write_all(&self.skey())?;
file.write_all(&self.siv())?;
Ok(())
}
}
#[derive(Debug, Clone)]
pub struct Aes256CbcCodec {
cipher: Aes256,
key: B256,
iv: B128,
padding: Padding,
}
impl Aes256CbcCodec {
pub fn new(key: B256, iv: B128) -> Aes256CbcCodec {
let padding = Padding::Ansix923(Ansix923::new(0xff as u8));
Aes256CbcCodec::new_with_padding(key, iv, padding)
}
pub fn new_with_padding(key: B256, iv: B128, padding: Padding) -> Aes256CbcCodec {
let gkey = GenericArray::from(key);
Aes256CbcCodec {
cipher: Aes256::new(&gkey),
key: key,
iv: iv,
padding: padding,
}
}
pub fn new_with_key(key: Aes256Key) -> Aes256CbcCodec {
let padding = Padding::Ansix923(Ansix923::new(0xff as u8));
let gkey = key.skey();
let giv = key.siv();
Aes256CbcCodec {
cipher: Aes256::new(&GenericArray::from(gkey)),
key: gkey,
iv: giv,
padding: padding,
}
}
pub fn encrypt_first_block(&self, input_block: &[u8]) -> Vec<u8> {
self.encrypt_block(input_block, &self.iv)
}
pub fn cipher(&self) -> Aes256 {
Aes256::new(&(self.key).into())
}
}
impl EncryptionEngine for Aes256CbcCodec {
fn encrypt_block(&self, plaintext: &[u8], xor_block: &[u8]) -> Vec<u8> {
let mut input_block = xor(&plaintext, &xor_block);
let mut output_block = GenericArray::from_mut_slice(input_block.as_mut_slice());
self.cipher.encrypt_block(&mut output_block);
output_block.as_slice().to_vec()
}
fn encrypt_blocks(&self, plaintext: &[u8]) -> Vec<u8> {
let mut result: Vec<Vec<u8>> = Vec::new();
let chunks: Vec<Vec<u8>> = plaintext.chunks(16).map(|c| c.to_vec()).collect();
let count = chunks.len();
for (index, block) in chunks.iter().enumerate() {
let xor_block = if index == 0 {
&self.iv
} else {
result[index - 1].as_slice()
};
let last_block_pos = count - 1;
let block = &if index == last_block_pos && block.len() < 16 {
self.padding.pad(&block).to_vec()
} else {
block.to_vec()
};
result.push(self.encrypt_block(block, xor_block));
}
let opaque: Vec<u8> = result.iter().flatten().map(|b| b.clone()).collect();
opaque
}
fn decrypt_blocks(&self, ciphertext: &[u8]) -> Vec<u8> {
let mut result: Vec<Vec<u8>> = Vec::new();
let chunks: Vec<Vec<u8>> = ciphertext.chunks(16).map(|c| c.to_vec()).collect();
let count = chunks.len();
let last_block_pos = count - 1;
for (index, block) in chunks.iter().enumerate() {
let xor_block = if index == 0 {
&self.iv
} else {
chunks[index - 1].as_slice()
};
let block = self.decrypt_block(block, xor_block);
result.push(if index == last_block_pos {
self.padding.unpad(&block)
} else {
block
});
}
result.iter().flatten().map(|b| b.clone()).collect()
}
fn decrypt_block(&self, ciphertext: &[u8], xor_block: &[u8]) -> Vec<u8> {
let mut ciphertext = ciphertext.to_vec();
let mut plaintext = GenericArray::from_mut_slice(ciphertext.as_mut_slice());
self.cipher.decrypt_block(&mut plaintext);
xor(&plaintext.as_slice(), &xor_block).to_vec()
}
}
#[cfg(test)]
mod aes256cbc_tests {
use crate::aescbc::cdc::{xor_128, Aes256CbcCodec, Aes256Key, EncryptionEngine, B128, B256};
use crate::aescbc::kd::pbkdf2_sha384_128bits;
use crate::aescbc::kd::pbkdf2_sha384_256bits;
use crate::aescbc::kd::DerivationScheme;
use crate::hashis::CrcAlgo;
use crate::ioutils::read_bytes;
use aes::cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit};
use aes::Aes256;
use k9::assert_equal;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct Block {
pub plaintext: B128,
pub input: B128,
pub output: B128,
pub ciphertext: B128,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Aes256CBCTestCase {
pub key: B256,
pub iv: B128,
pub blocks: Vec<Block>,
}
impl Aes256CBCTestCase {
pub fn block_at(&self, index: usize) -> Block {
self.blocks.get(index).unwrap().clone()
}
}
pub fn nist_cbc_aes256_encryption_test_input() -> Aes256CBCTestCase {
let encryption_blocks = [
Block {
plaintext: [
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
0x93, 0x17, 0x2a,
],
input: [
0x6b, 0xc0, 0xbc, 0xe1, 0x2a, 0x45, 0x99, 0x91, 0xe1, 0x34, 0x74, 0x1a, 0x7f,
0x9e, 0x19, 0x25,
],
output: [
0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f,
0x7b, 0xfb, 0xd6,
],
ciphertext: [
0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f,
0x7b, 0xfb, 0xd6,
],
},
Block {
plaintext: [
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45,
0xaf, 0x8e, 0x51,
],
input: [
0x5b, 0xa1, 0xc6, 0x53, 0xc8, 0xe6, 0x5d, 0x26, 0xe9, 0x29, 0xc4, 0x57, 0x1a,
0xd4, 0x75, 0x87,
],
output: [
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6,
0x70, 0x2c, 0x7d,
],
ciphertext: [
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6,
0x70, 0x2c, 0x7d,
],
},
Block {
plaintext: [
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a,
0x0a, 0x52, 0xef,
],
input: [
0xac, 0x34, 0x52, 0xd0, 0xdd, 0x87, 0x64, 0x9c, 0x82, 0x64, 0xb6, 0x62, 0xdc,
0x7a, 0x7e, 0x92,
],
output: [
0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04,
0x23, 0x14, 0x61,
],
ciphertext: [
0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04,
0x23, 0x14, 0x61,
],
},
Block {
plaintext: [
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6,
0x6c, 0x37, 0x10,
],
input: [
0xcf, 0x6d, 0x17, 0x2c, 0x76, 0x96, 0x21, 0xd8, 0x08, 0x1b, 0xa3, 0x18, 0xe2,
0x4f, 0x23, 0x71,
],
output: [
0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c,
0x6a, 0x9d, 0x1b,
],
ciphertext: [
0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c,
0x6a, 0x9d, 0x1b,
],
},
];
return Aes256CBCTestCase {
key: [
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d,
0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3,
0x09, 0x14, 0xdf, 0xf4,
],
iv: [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f,
],
blocks: encryption_blocks.to_vec(),
};
}
pub fn nist_cbc_aes256_decryption_test_input() -> Aes256CBCTestCase {
let decryption_blocks = [
Block {
ciphertext: [
0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f,
0x7b, 0xfb, 0xd6,
],
input: [
0xf5, 0x8c, 0x4c, 0x04, 0xd6, 0xe5, 0xf1, 0xba, 0x77, 0x9e, 0xab, 0xfb, 0x5f,
0x7b, 0xfb, 0xd6,
],
output: [
0x6b, 0xc0, 0xbc, 0xe1, 0x2a, 0x45, 0x99, 0x91, 0xe1, 0x34, 0x74, 0x1a, 0x7f,
0x9e, 0x19, 0x25,
],
plaintext: [
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73,
0x93, 0x17, 0x2a,
],
},
Block {
ciphertext: [
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6,
0x70, 0x2c, 0x7d,
],
input: [
0x9c, 0xfc, 0x4e, 0x96, 0x7e, 0xdb, 0x80, 0x8d, 0x67, 0x9f, 0x77, 0x7b, 0xc6,
0x70, 0x2c, 0x7d,
],
output: [
0x5b, 0xa1, 0xc6, 0x53, 0xc8, 0xe6, 0x5d, 0x26, 0xe9, 0x29, 0xc4, 0x57, 0x1a,
0xd4, 0x75, 0x87,
],
plaintext: [
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45,
0xaf, 0x8e, 0x51,
],
},
Block {
ciphertext: [
0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04,
0x23, 0x14, 0x61,
],
input: [
0x39, 0xf2, 0x33, 0x69, 0xa9, 0xd9, 0xba, 0xcf, 0xa5, 0x30, 0xe2, 0x63, 0x04,
0x23, 0x14, 0x61,
],
output: [
0xac, 0x34, 0x52, 0xd0, 0xdd, 0x87, 0x64, 0x9c, 0x82, 0x64, 0xb6, 0x62, 0xdc,
0x7a, 0x7e, 0x92,
],
plaintext: [
0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a,
0x0a, 0x52, 0xef,
],
},
Block {
ciphertext: [
0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c,
0x6a, 0x9d, 0x1b,
],
input: [
0xb2, 0xeb, 0x05, 0xe2, 0xc3, 0x9b, 0xe9, 0xfc, 0xda, 0x6c, 0x19, 0x07, 0x8c,
0x6a, 0x9d, 0x1b,
],
output: [
0xcf, 0x6d, 0x17, 0x2c, 0x76, 0x96, 0x21, 0xd8, 0x08, 0x1b, 0xa3, 0x18, 0xe2,
0x4f, 0x23, 0x71,
],
plaintext: [
0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6,
0x6c, 0x37, 0x10,
],
},
];
return Aes256CBCTestCase {
key: [
0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d,
0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3,
0x09, 0x14, 0xdf, 0xf4,
],
iv: [
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
0x0e, 0x0f,
],
blocks: decryption_blocks.to_vec(),
};
}
#[test]
pub fn test_confirm_cbc_aes256_nist_spec_encrypt_single_block() {
let encryption_input = nist_cbc_aes256_encryption_test_input();
let key = GenericArray::from(encryption_input.key);
let iv = encryption_input.iv.clone();
let cipher = Aes256::new(&key);
let block1 = encryption_input.block_at(0);
let block1_plaintext = block1.plaintext.clone();
let xor_input = xor_128(block1_plaintext, iv);
assert_equal!(xor_input, block1.input);
let mut block1_input = GenericArray::from(block1.input);
let block1_input_copy = block1_input.clone();
cipher.encrypt_block(&mut block1_input);
assert_equal!(
block1_input,
GenericArray::from(encryption_input.blocks[0].ciphertext)
);
assert_equal!(
block1_input,
GenericArray::from(encryption_input.blocks[0].output)
);
cipher.decrypt_block(&mut block1_input);
assert_equal!(
block1_input,
GenericArray::from(encryption_input.blocks[0].input)
);
assert_equal!(block1_input, block1_input_copy);
}
#[test]
pub fn test_confirm_cbc_aes256_nist_spec_decrypt_single_block() {
let decryption_input = nist_cbc_aes256_decryption_test_input();
let key = GenericArray::from(decryption_input.key);
let iv = decryption_input.iv.clone();
let cipher = Aes256::new(&key);
let block1 = decryption_input.block_at(0);
let block1_output = block1.output.clone();
let xor_output = xor_128(block1_output, iv);
assert_equal!(xor_output, block1.plaintext);
let mut block1_input = GenericArray::from(block1.input);
let block1_input_copy = block1_input.clone();
cipher.decrypt_block(&mut block1_input);
assert_equal!(
block1_input,
GenericArray::from(decryption_input.blocks[0].output)
);
assert_equal!(
block1_input,
GenericArray::from(xor_128(decryption_input.blocks[0].plaintext, iv))
);
cipher.encrypt_block(&mut block1_input);
assert_equal!(
block1_input,
GenericArray::from(decryption_input.blocks[0].input)
);
assert_equal!(block1_input, block1_input_copy);
}
#[test]
pub fn test_codec_encrypt_first_block() {
let encryption_input = nist_cbc_aes256_encryption_test_input();
let cdc = Aes256CbcCodec::new(encryption_input.key, encryption_input.iv);
let block1 = encryption_input.block_at(0);
let encrypted_ptf = cdc.encrypt_first_block(&block1.plaintext);
let encrypted_ptx = cdc.encrypt_block(&block1.plaintext, &cdc.iv);
assert_equal!(encrypted_ptf, block1.ciphertext.to_vec());
assert_equal!(encrypted_ptx, block1.ciphertext.to_vec());
assert_equal!(encrypted_ptf, block1.output.to_vec());
assert_equal!(encrypted_ptx, block1.output.to_vec());
let decrypted_ct = cdc.decrypt_block(&block1.ciphertext, &cdc.iv);
assert_equal!(decrypted_ct, block1.plaintext);
assert_equal!(decrypted_ct, xor_128(block1.input, cdc.iv));
}
#[test]
pub fn test_codec_decrypt_first_block() {
let decryption_input = nist_cbc_aes256_decryption_test_input();
let cdc = Aes256CbcCodec::new(decryption_input.key, decryption_input.iv);
let block1 = decryption_input.block_at(0);
let decrypted_ptx = cdc.decrypt_block(&block1.ciphertext, &decryption_input.iv);
let empty_mask = [0u8; 16];
let decrypted_ptz = cdc.decrypt_block(&block1.ciphertext, &empty_mask);
assert_equal!(decrypted_ptx, block1.plaintext.to_vec());
assert_equal!(decrypted_ptz, block1.output.to_vec());
let encrypted_pt = cdc.encrypt_block(&block1.plaintext, &decryption_input.iv);
assert_equal!(encrypted_pt, block1.ciphertext);
assert_equal!(encrypted_pt, block1.ciphertext);
}
#[test]
pub fn test_codec_aes256_cbc_transcript_nist_spec_encrypt_four_blocks() {
let encryption_input = nist_cbc_aes256_encryption_test_input();
let cdc = Aes256CbcCodec::new(encryption_input.key, encryption_input.iv);
let expected_plaintext: Vec<u8> = encryption_input
.blocks
.iter()
.map(|b| b.plaintext)
.flatten()
.collect();
let expected_ciphertext: Vec<u8> = encryption_input
.blocks
.iter()
.map(|b| b.ciphertext)
.flatten()
.collect();
let ciphertext = cdc.encrypt_blocks(&expected_plaintext);
assert_equal!(ciphertext, expected_ciphertext);
let plaintext = cdc.decrypt_blocks(&ciphertext);
assert_equal!(plaintext, expected_plaintext);
}
#[test]
pub fn test_codec_aes256_cbc_transcript_arbitraryly_sized_buffer() {
let key = [71u8; 32];
let iv = [84u8; 16];
let plaintext = read_bytes("tests/plaintext.jpg").unwrap();
let plaintext_length = plaintext.len();
let cdc = Aes256CbcCodec::new(key, iv);
let ciphertext = cdc.encrypt_blocks(&plaintext);
let decrypted = cdc.decrypt_blocks(&ciphertext);
assert_equal!(decrypted.len() - plaintext_length, 0);
assert_equal!(decrypted.len(), plaintext_length);
assert_equal!(plaintext, decrypted);
}
#[test]
pub fn test_codec_aes256_cbc_encrypt_pbkdf2_key_and_iv() {
let key = pbkdf2_sha384_256bits(b"cypher where is tank?", b"soul society", 83);
let iv = pbkdf2_sha384_128bits(b"84 + 4(vier(six-he/saw him/vejo ele/vejo him/vejo rim(kidney - human organ that processes fear))((fear / four + fe' ar + avatar))) == X == ascii code 88", b"GO = 'George Orwell' = 4 in japanese. O shit we're back on fear...", 88); let plaintext = read_bytes("tests/plaintext.jpg").unwrap();
let plaintext_length = plaintext.len();
let cdc = Aes256CbcCodec::new(key, iv);
let ciphertext = cdc.encrypt_blocks(&plaintext);
let decrypted = cdc.decrypt_blocks(&ciphertext);
assert_equal!(decrypted.len() - plaintext_length, 0);
assert_equal!(decrypted.len(), plaintext_length);
assert_equal!(plaintext, decrypted);
}
#[test]
pub fn test_codec_aes256_cbc_encrypt_derive() {
let password = "cypher where is tank?".to_string();
let salt = "soul society".to_string();
let key = Aes256Key::derive(
[password].to_vec(),
u64::MAX,
[salt].to_vec(),
u64::MAX,
0x35,
DerivationScheme::Crc(CrcAlgo::GcRc256),
false,
)
.expect("it appears that the key cannot be derived in this instant");
let plaintext = read_bytes("tests/plaintext.jpg").unwrap();
let plaintext_length = plaintext.len();
let cdc = Aes256CbcCodec::new_with_key(key);
let ciphertext = cdc.encrypt_blocks(&plaintext);
let decrypted = cdc.decrypt_blocks(&ciphertext);
assert_equal!(decrypted.len() - plaintext_length, 0);
assert_equal!(decrypted.len(), plaintext_length);
assert_equal!(plaintext, decrypted);
}
}