#[cfg(feature = "emulation")]
use std::iter::repeat_n;
use aes::Aes128;
use cbc::cipher::block_padding::{NoPadding, Pkcs7};
use cbc::cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyInit, KeyIvInit};
use cbc::{Decryptor, Encryptor};
#[cfg(feature = "legacy-crypto")]
use des::{Des, TdesEde3};
use ecb::{Decryptor as EcbDecryptor, Encryptor as EcbEncryptor};
use hmac::{Hmac, KeyInit as HmacKeyInit, Mac};
#[cfg(feature = "legacy-crypto")]
use md5::{Digest as Md5Digest, Md5};
#[cfg(feature = "emulation")]
use num_bigint::BigUint;
use pbkdf2::pbkdf2_hmac;
#[cfg(feature = "legacy-crypto")]
use sha1::{Digest as Sha1Digest, Sha1};
use sha2::{Digest as Sha2Digest, Sha256, Sha384, Sha512};
type Aes128CbcEnc = Encryptor<Aes128>;
type Aes128CbcDec = Decryptor<Aes128>;
type Aes192CbcEnc = Encryptor<aes::Aes192>;
type Aes192CbcDec = Decryptor<aes::Aes192>;
type Aes256CbcEnc = Encryptor<aes::Aes256>;
type Aes256CbcDec = Decryptor<aes::Aes256>;
type Aes128EcbEnc = EcbEncryptor<Aes128>;
type Aes128EcbDec = EcbDecryptor<Aes128>;
type Aes192EcbEnc = EcbEncryptor<aes::Aes192>;
type Aes192EcbDec = EcbDecryptor<aes::Aes192>;
type Aes256EcbEnc = EcbEncryptor<aes::Aes256>;
type Aes256EcbDec = EcbDecryptor<aes::Aes256>;
#[cfg(feature = "legacy-crypto")]
type DesCbcEnc = Encryptor<Des>;
#[cfg(feature = "legacy-crypto")]
type DesCbcDec = Decryptor<Des>;
#[cfg(feature = "legacy-crypto")]
type TdesCbcEnc = Encryptor<TdesEde3>;
#[cfg(feature = "legacy-crypto")]
type TdesCbcDec = Decryptor<TdesEde3>;
#[cfg(feature = "legacy-crypto")]
type DesEcbEnc = EcbEncryptor<Des>;
#[cfg(feature = "legacy-crypto")]
type DesEcbDec = EcbDecryptor<Des>;
#[cfg(feature = "legacy-crypto")]
type TdesEcbEnc = EcbEncryptor<TdesEde3>;
#[cfg(feature = "legacy-crypto")]
type TdesEcbDec = EcbDecryptor<TdesEde3>;
#[cfg(feature = "legacy-crypto")]
#[must_use]
pub fn compute_md5(data: &[u8]) -> Vec<u8> {
let mut hasher = Md5::new();
Md5Digest::update(&mut hasher, data);
hasher.finalize().to_vec()
}
#[cfg(feature = "legacy-crypto")]
#[must_use]
pub fn compute_sha1(data: &[u8]) -> Vec<u8> {
let mut hasher = Sha1::new();
Sha1Digest::update(&mut hasher, data);
hasher.finalize().to_vec()
}
#[must_use]
pub fn compute_sha256(data: &[u8]) -> Vec<u8> {
let mut hasher = Sha256::new();
Sha2Digest::update(&mut hasher, data);
hasher.finalize().to_vec()
}
#[must_use]
pub fn compute_sha384(data: &[u8]) -> Vec<u8> {
let mut hasher = Sha384::new();
Sha2Digest::update(&mut hasher, data);
hasher.finalize().to_vec()
}
#[must_use]
pub fn compute_sha512(data: &[u8]) -> Vec<u8> {
let mut hasher = Sha512::new();
Sha2Digest::update(&mut hasher, data);
hasher.finalize().to_vec()
}
#[must_use]
pub fn compute_hmac_sha256(key: &[u8], data: &[u8]) -> Vec<u8> {
type HmacSha256 = Hmac<Sha256>;
let Ok(mut mac) = <HmacSha256 as HmacKeyInit>::new_from_slice(key) else {
return Vec::new();
};
mac.update(data);
mac.finalize().into_bytes().to_vec()
}
#[must_use]
pub fn compute_hmac_sha512(key: &[u8], data: &[u8]) -> Vec<u8> {
type HmacSha512 = Hmac<Sha512>;
let Ok(mut mac) = <HmacSha512 as HmacKeyInit>::new_from_slice(key) else {
return Vec::new();
};
mac.update(data);
mac.finalize().into_bytes().to_vec()
}
pub fn derive_pbkdf2_key(
password: &[u8],
salt: &[u8],
iterations: u32,
key_len: usize,
hash_algorithm: &str,
) -> Vec<u8> {
let mut key = vec![0u8; key_len];
match hash_algorithm.to_uppercase().as_str() {
"SHA256" => {
pbkdf2_hmac::<sha2::Sha256>(password, salt, iterations, &mut key);
}
"SHA384" => {
pbkdf2_hmac::<sha2::Sha384>(password, salt, iterations, &mut key);
}
"SHA512" => {
pbkdf2_hmac::<sha2::Sha512>(password, salt, iterations, &mut key);
}
#[cfg(feature = "legacy-crypto")]
_ => {
pbkdf2_hmac::<sha1::Sha1>(password, salt, iterations, &mut key);
}
#[cfg(not(feature = "legacy-crypto"))]
_ => {
pbkdf2_hmac::<sha2::Sha256>(password, salt, iterations, &mut key);
}
}
key
}
#[cfg(feature = "legacy-crypto")]
pub fn derive_pbkdf1_key(password: &[u8], salt: &[u8], iterations: u32, key_len: usize) -> Vec<u8> {
let mut hasher = sha1::Sha1::new();
hasher.update(password);
hasher.update(salt);
let mut t = hasher.finalize();
for _ in 1..iterations {
let mut hasher = sha1::Sha1::new();
hasher.update(t);
t = hasher.finalize();
}
let base_key: [u8; 20] = t.into();
if key_len <= 20 {
base_key[..key_len].to_vec()
} else {
let mut result = base_key.to_vec();
let mut counter = 1u32;
while result.len() < key_len {
let mut hasher = sha1::Sha1::new();
hasher.update(counter.to_string().as_bytes());
hasher.update(base_key);
let block = hasher.finalize();
result.extend_from_slice(&block);
counter += 1;
}
result.truncate(key_len);
result
}
}
pub fn apply_crypto_transform(
algorithm: &str,
key: &[u8],
iv: &[u8],
is_encryptor: bool,
data: &[u8],
mode: u8,
padding: u8,
) -> Option<Vec<u8>> {
let alg_upper = algorithm.to_uppercase();
let is_ecb = mode == 2;
if alg_upper.contains("AES") || alg_upper.contains("RIJNDAEL") {
return if is_ecb {
aes_ecb_transform(key, is_encryptor, data, padding)
} else {
aes_cbc_transform(key, iv, is_encryptor, data, padding)
};
}
#[cfg(feature = "legacy-crypto")]
if alg_upper.contains("TRIPLEDES") || alg_upper.contains("3DES") {
if key.len() == 24 {
return if is_ecb {
tdes_ecb_transform(key, is_encryptor, data, padding)
} else if iv.len() >= 8 {
tdes_cbc_transform(key, iv, is_encryptor, data, padding)
} else {
None
};
}
return None;
}
#[cfg(feature = "legacy-crypto")]
if alg_upper.contains("DES") {
if key.len() == 8 {
return if is_ecb {
des_ecb_transform(key, is_encryptor, data, padding)
} else if iv.len() >= 8 {
des_cbc_transform(key, iv, is_encryptor, data, padding)
} else {
None
};
}
return None;
}
#[cfg(not(feature = "legacy-crypto"))]
if alg_upper.contains("DES") {
return None;
}
None
}
fn aes_cbc_transform(
key: &[u8],
iv: &[u8],
is_encryptor: bool,
data: &[u8],
padding: u8,
) -> Option<Vec<u8>> {
match key.len() {
16 => cbc_transform::<Aes128CbcEnc, Aes128CbcDec>(key, iv, 16, is_encryptor, data, padding),
24 => cbc_transform::<Aes192CbcEnc, Aes192CbcDec>(key, iv, 16, is_encryptor, data, padding),
32 => cbc_transform::<Aes256CbcEnc, Aes256CbcDec>(key, iv, 16, is_encryptor, data, padding),
_ => None,
}
}
fn aes_ecb_transform(key: &[u8], is_encryptor: bool, data: &[u8], padding: u8) -> Option<Vec<u8>> {
match key.len() {
16 => ecb_transform::<Aes128EcbEnc, Aes128EcbDec>(key, 16, is_encryptor, data, padding),
24 => ecb_transform::<Aes192EcbEnc, Aes192EcbDec>(key, 16, is_encryptor, data, padding),
32 => ecb_transform::<Aes256EcbEnc, Aes256EcbDec>(key, 16, is_encryptor, data, padding),
_ => None,
}
}
fn cbc_transform<E, D>(
key: &[u8],
iv: &[u8],
block_size: usize,
is_encryptor: bool,
data: &[u8],
padding: u8,
) -> Option<Vec<u8>>
where
E: BlockModeEncrypt + KeyIvInit,
D: BlockModeDecrypt + KeyIvInit,
{
if iv.len() < block_size {
return None;
}
if is_encryptor {
let cipher = E::new_from_slices(key, &iv[..block_size]).ok()?;
let padded_len = ((data.len() / block_size) + 1) * block_size;
let mut buf = vec![0u8; padded_len];
buf[..data.len()].copy_from_slice(data);
let result = match padding {
1 => cipher
.encrypt_padded::<NoPadding>(&mut buf, data.len())
.ok()?,
3 => {
let result = cipher
.encrypt_padded::<NoPadding>(&mut buf, padded_len)
.ok()?;
return Some(result.to_vec());
}
_ => cipher.encrypt_padded::<Pkcs7>(&mut buf, data.len()).ok()?,
};
Some(result.to_vec())
} else {
if data.is_empty() {
return None;
}
let cipher = D::new_from_slices(key, &iv[..block_size]).ok()?;
let mut buf = data.to_vec();
let result = match padding {
1 | 3 => cipher.decrypt_padded::<NoPadding>(&mut buf).ok()?,
_ => cipher.decrypt_padded::<Pkcs7>(&mut buf).ok()?,
};
Some(result.to_vec())
}
}
fn ecb_transform<E, D>(
key: &[u8],
block_size: usize,
is_encryptor: bool,
data: &[u8],
padding: u8,
) -> Option<Vec<u8>>
where
E: BlockModeEncrypt + KeyInit,
D: BlockModeDecrypt + KeyInit,
{
if is_encryptor {
let cipher = E::new_from_slice(key).ok()?;
let padded_len = ((data.len() / block_size) + 1) * block_size;
let mut buf = vec![0u8; padded_len];
buf[..data.len()].copy_from_slice(data);
let result = match padding {
1 => cipher
.encrypt_padded::<NoPadding>(&mut buf, data.len())
.ok()?,
3 => {
let result = cipher
.encrypt_padded::<NoPadding>(&mut buf, padded_len)
.ok()?;
return Some(result.to_vec());
}
_ => cipher.encrypt_padded::<Pkcs7>(&mut buf, data.len()).ok()?,
};
Some(result.to_vec())
} else {
if data.is_empty() {
return None;
}
let cipher = D::new_from_slice(key).ok()?;
let mut buf = data.to_vec();
let result = match padding {
1 | 3 => cipher.decrypt_padded::<NoPadding>(&mut buf).ok()?,
_ => cipher.decrypt_padded::<Pkcs7>(&mut buf).ok()?,
};
Some(result.to_vec())
}
}
#[cfg(feature = "legacy-crypto")]
fn des_cbc_transform(
key: &[u8],
iv: &[u8],
is_encryptor: bool,
data: &[u8],
padding: u8,
) -> Option<Vec<u8>> {
cbc_transform::<DesCbcEnc, DesCbcDec>(key, iv, 8, is_encryptor, data, padding)
}
#[cfg(feature = "legacy-crypto")]
fn des_ecb_transform(key: &[u8], is_encryptor: bool, data: &[u8], padding: u8) -> Option<Vec<u8>> {
ecb_transform::<DesEcbEnc, DesEcbDec>(key, 8, is_encryptor, data, padding)
}
#[cfg(feature = "legacy-crypto")]
fn tdes_cbc_transform(
key: &[u8],
iv: &[u8],
is_encryptor: bool,
data: &[u8],
padding: u8,
) -> Option<Vec<u8>> {
cbc_transform::<TdesCbcEnc, TdesCbcDec>(key, iv, 8, is_encryptor, data, padding)
}
#[cfg(feature = "legacy-crypto")]
fn tdes_ecb_transform(key: &[u8], is_encryptor: bool, data: &[u8], padding: u8) -> Option<Vec<u8>> {
ecb_transform::<TdesEcbEnc, TdesEcbDec>(key, 8, is_encryptor, data, padding)
}
#[cfg(feature = "emulation")]
pub fn verify_rsa_pkcs1v15(
modulus: &[u8],
exponent: &[u8],
hash: &[u8],
signature: &[u8],
hash_algorithm: &str,
) -> bool {
let digest_prefix: &[u8] = match hash_algorithm.to_uppercase().as_str() {
"SHA256" | "2.16.840.1.101.3.4.2.1" => &[
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
0x01, 0x05, 0x00, 0x04, 0x20,
],
"SHA384" | "2.16.840.1.101.3.4.2.2" => &[
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
0x02, 0x05, 0x00, 0x04, 0x30,
],
"SHA512" | "2.16.840.1.101.3.4.2.3" => &[
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02,
0x03, 0x05, 0x00, 0x04, 0x40,
],
#[cfg(feature = "legacy-crypto")]
"SHA1" | "1.3.14.3.2.26" => &[
0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
0x14,
],
_ => return false,
};
let n = BigUint::from_bytes_be(modulus);
let e = BigUint::from_bytes_be(exponent);
let s = BigUint::from_bytes_be(signature);
if s >= n {
return false;
}
let m = s.modpow(&e, &n);
let k = modulus.len();
let m_bytes = m.to_bytes_be();
if m_bytes.len() > k {
return false;
}
let mut em = vec![0u8; k];
em[k - m_bytes.len()..].copy_from_slice(&m_bytes);
let t_len = digest_prefix.len() + hash.len();
if k < t_len + 11 {
return false;
}
let ps_len = k - t_len - 3;
let mut expected = Vec::with_capacity(k);
expected.push(0x00);
expected.push(0x01);
expected.extend(repeat_n(0xFF, ps_len));
expected.push(0x00);
expected.extend_from_slice(digest_prefix);
expected.extend_from_slice(hash);
em == expected
}
#[derive(Debug, Clone)]
pub struct CryptoParameters {
pub iterations: u32,
pub key_size: usize,
pub iv_size: usize,
pub hash_algorithm: &'static str,
}
impl Default for CryptoParameters {
fn default() -> Self {
Self {
iterations: 1000,
key_size: 32,
iv_size: 16,
hash_algorithm: "SHA1",
}
}
}
pub fn derive_key_iv(
password: &[u8],
salt: &[u8],
params: &CryptoParameters,
) -> (Vec<u8>, Vec<u8>) {
let output_len = params.key_size + params.iv_size;
let derived = derive_pbkdf2_key(
password,
salt,
params.iterations,
output_len,
params.hash_algorithm,
);
(
derived[..params.key_size].to_vec(),
derived[params.key_size..output_len].to_vec(),
)
}
#[cfg(test)]
mod tests {
use crate::utils::crypto::derive_pbkdf2_key;
#[test]
fn test_pbkdf2_sha256_basic() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf2_key(password, salt, 1, 32, "SHA256");
assert_eq!(key.len(), 32);
let key2 = derive_pbkdf2_key(password, salt, 1, 32, "SHA256");
assert_eq!(key, key2);
}
#[test]
fn test_pbkdf2_sha384() {
let password = b"test";
let salt = b"salt123";
let key = derive_pbkdf2_key(password, salt, 1000, 48, "SHA384");
assert_eq!(key.len(), 48);
}
#[test]
fn test_pbkdf2_sha512() {
let password = b"test";
let salt = b"salt123";
let key = derive_pbkdf2_key(password, salt, 1000, 64, "SHA512");
assert_eq!(key.len(), 64);
}
#[test]
fn test_pbkdf2_iterations_affect_output() {
let password = b"password";
let salt = b"salt";
let key_1 = derive_pbkdf2_key(password, salt, 1, 20, "SHA256");
let key_1000 = derive_pbkdf2_key(password, salt, 1000, 20, "SHA256");
assert_ne!(key_1, key_1000);
}
#[test]
fn test_pbkdf2_salt_affects_output() {
let password = b"password";
let salt1 = b"salt1";
let salt2 = b"salt2";
let key1 = derive_pbkdf2_key(password, salt1, 1000, 20, "SHA256");
let key2 = derive_pbkdf2_key(password, salt2, 1000, 20, "SHA256");
assert_ne!(key1, key2);
}
#[test]
fn test_pbkdf2_case_insensitive_algorithm() {
let password = b"test";
let salt = b"salt";
let key_upper = derive_pbkdf2_key(password, salt, 1, 32, "SHA256");
let key_lower = derive_pbkdf2_key(password, salt, 1, 32, "sha256");
let key_mixed = derive_pbkdf2_key(password, salt, 1, 32, "Sha256");
assert_eq!(key_upper, key_lower);
assert_eq!(key_upper, key_mixed);
}
#[test]
fn test_pbkdf2_empty_password() {
let password = b"";
let salt = b"salt";
let key = derive_pbkdf2_key(password, salt, 1000, 16, "SHA256");
assert_eq!(key.len(), 16);
assert!(key.iter().any(|&b| b != 0));
}
#[test]
fn test_pbkdf2_empty_salt() {
let password = b"password";
let salt = b"";
let key = derive_pbkdf2_key(password, salt, 1000, 16, "SHA256");
assert_eq!(key.len(), 16);
}
#[test]
fn test_pbkdf2_variable_key_length() {
let password = b"password";
let salt = b"salt";
for len in [1, 16, 20, 32, 48, 64, 100] {
let key = derive_pbkdf2_key(password, salt, 1, len, "SHA256");
assert_eq!(key.len(), len);
}
}
use super::apply_crypto_transform;
#[test]
fn test_aes_128_encrypt_decrypt() {
let key = [0u8; 16]; let iv = [0u8; 16]; let plaintext = b"Hello, World!";
let ciphertext = apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2);
assert!(ciphertext.is_some(), "Encryption should succeed");
let ciphertext = ciphertext.unwrap();
assert_ne!(
ciphertext.as_slice(),
plaintext,
"Ciphertext should differ from plaintext"
);
let decrypted = apply_crypto_transform("AES", &key, &iv, false, &ciphertext, 1, 2);
assert!(decrypted.is_some(), "Decryption should succeed");
assert_eq!(
decrypted.unwrap(),
plaintext,
"Decrypted should match original"
);
}
#[test]
fn test_aes_192_encrypt_decrypt() {
let key = [0u8; 24]; let iv = [0u8; 16];
let plaintext = b"Test message for AES-192";
let ciphertext = apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2).unwrap();
let decrypted = apply_crypto_transform("AES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_aes_256_encrypt_decrypt() {
let key = [0u8; 32]; let iv = [0u8; 16];
let plaintext = b"Test message for AES-256";
let ciphertext = apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2).unwrap();
let decrypted = apply_crypto_transform("AES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_rijndael_alias() {
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = b"Test for Rijndael";
let ciphertext =
apply_crypto_transform("Rijndael", &key, &iv, true, plaintext, 1, 2).unwrap();
let decrypted =
apply_crypto_transform("Rijndael", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
let aes_ciphertext =
apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2).unwrap();
assert_eq!(ciphertext, aes_ciphertext);
}
#[test]
fn test_unsupported_key_size() {
let bad_key = [0u8; 15]; let iv = [0u8; 16];
let plaintext = b"test";
let result = apply_crypto_transform("AES", &bad_key, &iv, true, plaintext, 1, 2);
assert!(result.is_none(), "Should fail with invalid key size");
}
#[test]
fn test_unsupported_algorithm() {
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = b"test";
let result = apply_crypto_transform("UNKNOWN_ALGO", &key, &iv, true, plaintext, 1, 2);
assert!(result.is_none(), "Should return None for unknown algorithm");
}
#[test]
fn test_case_insensitive_algorithm() {
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = b"case test";
let ct1 = apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2).unwrap();
let ct2 = apply_crypto_transform("aes", &key, &iv, true, plaintext, 1, 2).unwrap();
let ct3 = apply_crypto_transform("Aes", &key, &iv, true, plaintext, 1, 2).unwrap();
assert_eq!(ct1, ct2);
assert_eq!(ct1, ct3);
}
#[test]
fn test_different_keys_produce_different_ciphertext() {
let key1 = [0u8; 16];
let key2 = [1u8; 16];
let iv = [0u8; 16];
let plaintext = b"test";
let ct1 = apply_crypto_transform("AES", &key1, &iv, true, plaintext, 1, 2).unwrap();
let ct2 = apply_crypto_transform("AES", &key2, &iv, true, plaintext, 1, 2).unwrap();
assert_ne!(ct1, ct2);
}
#[test]
fn test_different_ivs_produce_different_ciphertext() {
let key = [0u8; 16];
let iv1 = [0u8; 16];
let iv2 = [1u8; 16];
let plaintext = b"test";
let ct1 = apply_crypto_transform("AES", &key, &iv1, true, plaintext, 1, 2).unwrap();
let ct2 = apply_crypto_transform("AES", &key, &iv2, true, plaintext, 1, 2).unwrap();
assert_ne!(ct1, ct2);
}
#[test]
fn test_empty_plaintext() {
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = b"";
let ciphertext = apply_crypto_transform("AES", &key, &iv, true, plaintext, 1, 2).unwrap();
assert_eq!(ciphertext.len(), 16);
let decrypted = apply_crypto_transform("AES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert!(decrypted.is_empty());
}
#[test]
fn test_block_aligned_plaintext() {
let key = [0u8; 16];
let iv = [0u8; 16];
let plaintext = [0u8; 32];
let ciphertext = apply_crypto_transform("AES", &key, &iv, true, &plaintext, 1, 2).unwrap();
assert_eq!(ciphertext.len(), 48);
let decrypted = apply_crypto_transform("AES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
}
}
#[cfg(test)]
#[cfg(feature = "legacy-crypto")]
mod legacy_tests {
use crate::utils::crypto::{derive_pbkdf1_key, derive_pbkdf2_key};
use sha1::Digest;
#[test]
fn test_pbkdf2_sha1_basic() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf2_key(password, salt, 1, 20, "SHA1");
assert_eq!(key.len(), 20);
let key2 = derive_pbkdf2_key(password, salt, 1, 20, "SHA1");
assert_eq!(key, key2);
}
#[test]
fn test_pbkdf2_sha256_vs_sha1() {
let password = b"password";
let salt = b"salt";
let key_sha256 = derive_pbkdf2_key(password, salt, 1, 32, "SHA256");
let key_sha1 = derive_pbkdf2_key(password, salt, 1, 32, "SHA1");
assert_ne!(key_sha256, key_sha1);
}
#[test]
fn test_pbkdf2_unknown_algorithm_defaults_to_sha1() {
let password = b"test";
let salt = b"salt";
let key_unknown = derive_pbkdf2_key(password, salt, 1000, 20, "UNKNOWN");
let key_sha1 = derive_pbkdf2_key(password, salt, 1000, 20, "SHA1");
assert_eq!(key_unknown, key_sha1);
}
#[test]
fn test_pbkdf1_basic() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 100, 16);
assert_eq!(key.len(), 16);
let key2 = derive_pbkdf1_key(password, salt, 100, 16);
assert_eq!(key, key2);
}
#[test]
fn test_pbkdf1_max_natural_length() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 100, 20);
assert_eq!(key.len(), 20);
}
#[test]
fn test_pbkdf1_extended_length() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 100, 32);
assert_eq!(key.len(), 32);
}
#[test]
fn test_pbkdf1_very_long_key() {
let password = b"password";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 100, 100);
assert_eq!(key.len(), 100);
}
#[test]
fn test_pbkdf1_iterations_affect_output() {
let password = b"password";
let salt = b"salt";
let key_1 = derive_pbkdf1_key(password, salt, 1, 20);
let key_100 = derive_pbkdf1_key(password, salt, 100, 20);
assert_ne!(key_1, key_100);
}
#[test]
fn test_pbkdf1_salt_affects_output() {
let password = b"password";
let salt1 = b"salt1";
let salt2 = b"salt2";
let key1 = derive_pbkdf1_key(password, salt1, 100, 20);
let key2 = derive_pbkdf1_key(password, salt2, 100, 20);
assert_ne!(key1, key2);
}
#[test]
fn test_pbkdf1_password_affects_output() {
let password1 = b"password1";
let password2 = b"password2";
let salt = b"salt";
let key1 = derive_pbkdf1_key(password1, salt, 100, 20);
let key2 = derive_pbkdf1_key(password2, salt, 100, 20);
assert_ne!(key1, key2);
}
#[test]
fn test_pbkdf1_empty_password() {
let password = b"";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 100, 16);
assert_eq!(key.len(), 16);
}
#[test]
fn test_pbkdf1_empty_salt() {
let password = b"password";
let salt = b"";
let key = derive_pbkdf1_key(password, salt, 100, 16);
assert_eq!(key.len(), 16);
}
#[test]
fn test_pbkdf1_single_iteration() {
let password = b"test";
let salt = b"salt";
let key = derive_pbkdf1_key(password, salt, 1, 20);
let mut hasher = sha1::Sha1::new();
hasher.update(password);
hasher.update(salt);
let expected: [u8; 20] = hasher.finalize().into();
assert_eq!(key, expected);
}
#[test]
fn test_pbkdf1_variable_key_length() {
let password = b"password";
let salt = b"salt";
for len in [1, 8, 16, 20, 32, 48, 64] {
let key = derive_pbkdf1_key(password, salt, 100, len);
assert_eq!(key.len(), len);
}
}
#[test]
fn test_pbkdf1_different_from_pbkdf2() {
let password = b"password";
let salt = b"salt";
let key1 = derive_pbkdf1_key(password, salt, 100, 20);
let key2 = derive_pbkdf2_key(password, salt, 100, 20, "SHA1");
assert_ne!(key1, key2);
}
use super::apply_crypto_transform;
#[test]
fn test_des_encrypt_decrypt() {
let key = [0u8; 8]; let iv = [0u8; 8]; let plaintext = b"DES test";
let ciphertext = apply_crypto_transform("DES", &key, &iv, true, plaintext, 1, 2).unwrap();
let decrypted = apply_crypto_transform("DES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
}
#[test]
fn test_tripledes_encrypt_decrypt() {
let key = [0u8; 24]; let iv = [0u8; 8]; let plaintext = b"TripleDES test message";
let ciphertext =
apply_crypto_transform("TripleDES", &key, &iv, true, plaintext, 1, 2).unwrap();
let decrypted =
apply_crypto_transform("TripleDES", &key, &iv, false, &ciphertext, 1, 2).unwrap();
assert_eq!(decrypted, plaintext);
let ciphertext_3des =
apply_crypto_transform("3DES", &key, &iv, true, plaintext, 1, 2).unwrap();
assert_eq!(ciphertext, ciphertext_3des);
}
}