mirror of
https://github.com/bitwarden/browser
synced 2025-12-10 13:23:34 +00:00
Add unit tests to chromium importer (#16462)
* Add unit tests to chromium importer
This commit is contained in:
@@ -1,17 +1,51 @@
|
||||
//! Cryptographic primitives used in the SDK
|
||||
|
||||
use anyhow::{Result, anyhow};
|
||||
use anyhow::{anyhow, Result};
|
||||
|
||||
use aes::cipher::{
|
||||
block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, KeyIvInit,
|
||||
};
|
||||
|
||||
#[allow(clippy::question_mark)]
|
||||
pub fn decrypt_aes256(iv: &[u8; 16], data: &[u8], key: GenericArray<u8, U32>) -> Result<Vec<u8>> {
|
||||
let iv = GenericArray::from_slice(iv);
|
||||
let mut data = data.to_vec();
|
||||
return cbc::Decryptor::<aes::Aes256>::new(&key, iv)
|
||||
let result = cbc::Decryptor::<aes::Aes256>::new(&key, iv)
|
||||
.decrypt_padded_mut::<Pkcs7>(&mut data)
|
||||
.map_err(|_| anyhow!("Failed to decrypt data"))?;
|
||||
|
||||
.map_err(|_| anyhow!("Failed to decrypt data"));
|
||||
if let Err(e) = result {
|
||||
return Err(e);
|
||||
}
|
||||
Ok(data)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use aes::cipher::{
|
||||
generic_array::{sequence::GenericSequence, GenericArray},
|
||||
ArrayLength,
|
||||
};
|
||||
use base64::{engine::general_purpose::STANDARD, Engine};
|
||||
|
||||
pub fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec<u8> {
|
||||
(0..length).map(|i| offset + i as u8 * increment).collect()
|
||||
}
|
||||
pub fn generate_generic_array<N: ArrayLength<u8>>(
|
||||
offset: u8,
|
||||
increment: u8,
|
||||
) -> GenericArray<u8, N> {
|
||||
GenericArray::generate(|i| offset + i as u8 * increment)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decrypt_aes256() {
|
||||
let iv = generate_vec(16, 0, 1);
|
||||
let iv: &[u8; 16] = iv.as_slice().try_into().unwrap();
|
||||
let key = generate_generic_array(0, 1);
|
||||
let data: Vec<u8> = STANDARD.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap();
|
||||
|
||||
let decrypted = super::decrypt_aes256(iv, &data, key).unwrap();
|
||||
|
||||
assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!\u{6}\u{6}\u{6}\u{6}\u{6}\u{6}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ pub fn split_encrypted_string_and_validate<'a>(
|
||||
|
||||
pub fn decrypt_aes_128_cbc(key: &[u8], iv: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>> {
|
||||
let decryptor = cbc::Decryptor::<aes::Aes128>::new_from_slices(key, iv)?;
|
||||
let plaintext = decryptor
|
||||
let plaintext: Vec<u8> = decryptor
|
||||
.decrypt_padded_vec_mut::<Pkcs7>(ciphertext)
|
||||
.map_err(|e| anyhow!("Failed to decrypt: {}", e))?;
|
||||
Ok(plaintext)
|
||||
@@ -41,3 +41,110 @@ pub fn derive_saltysalt(password: &[u8], iterations: u32) -> Result<Vec<u8>> {
|
||||
.map_err(|e| anyhow!("Failed to derive master key: {}", e))?;
|
||||
Ok(key)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
pub fn generate_vec(length: usize, offset: u8, increment: u8) -> Vec<u8> {
|
||||
(0..length).map(|i| offset + i as u8 * increment).collect()
|
||||
}
|
||||
pub fn generate_generic_array<N: ArrayLength<u8>>(
|
||||
offset: u8,
|
||||
increment: u8,
|
||||
) -> GenericArray<u8, N> {
|
||||
GenericArray::generate(|i| offset + i as u8 * increment)
|
||||
}
|
||||
|
||||
use aes::cipher::{
|
||||
block_padding::Pkcs7,
|
||||
generic_array::{sequence::GenericSequence, GenericArray},
|
||||
ArrayLength, BlockEncryptMut, KeyIvInit,
|
||||
};
|
||||
|
||||
const LENGTH16: usize = 16;
|
||||
const LENGTH10: usize = 10;
|
||||
const LENGTH0: usize = 0;
|
||||
|
||||
fn run_split_encrypted_string_test<'a, const N: usize>(
|
||||
successfully_split: bool,
|
||||
plaintext_to_encrypt: &'a str,
|
||||
version: &'a str,
|
||||
password: Vec<u8>,
|
||||
) {
|
||||
let res = super::split_encrypted_string(plaintext_to_encrypt.as_bytes());
|
||||
|
||||
assert_eq!(res.is_ok(), successfully_split);
|
||||
if let Ok((version_found, password_found)) = res {
|
||||
assert_eq!(version_found, version);
|
||||
assert_eq!(password_found.len(), password.len());
|
||||
assert_eq!(password_found, &password);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_success_v10() {
|
||||
run_split_encrypted_string_test::<LENGTH0>(
|
||||
true,
|
||||
"v10EncryptMe!",
|
||||
"v10",
|
||||
vec![69, 110, 99, 114, 121, 112, 116, 77, 101, 33],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_fail_no_password() {
|
||||
run_split_encrypted_string_test::<LENGTH10>(true, "v09", "v09", Vec::<u8>::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_fail_too_small() {
|
||||
run_split_encrypted_string_test::<LENGTH10>(false, "v0", "v0", vec![0]);
|
||||
}
|
||||
|
||||
fn run_split_encrypted_string_and_validate_test(
|
||||
valid_version: bool,
|
||||
plaintext_to_encrypt: &str,
|
||||
supported_versions: &[&str],
|
||||
) {
|
||||
let result = super::split_encrypted_string_and_validate(
|
||||
plaintext_to_encrypt.as_bytes(),
|
||||
supported_versions,
|
||||
);
|
||||
assert_eq!(result.is_ok(), valid_version);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_and_validate_version_found_from_single_version() {
|
||||
run_split_encrypted_string_and_validate_test(true, "v10EncryptMe!", &["v10"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_and_validate_version_found_from_multiple_versions() {
|
||||
run_split_encrypted_string_and_validate_test(true, "v10EncryptMe!", &["v11", "v10"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_and_validate_version_not_found() {
|
||||
run_split_encrypted_string_and_validate_test(false, "v10EncryptMe!", &["v11", "v12"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_encrypted_string_and_validate_version_not_found_empty_list() {
|
||||
run_split_encrypted_string_and_validate_test(false, "v10EncryptMe!", &[]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_decrypt_aes_128_cbc() {
|
||||
let offset = 0;
|
||||
let increment = 1;
|
||||
|
||||
let iv = generate_vec(LENGTH16, offset, increment);
|
||||
let iv: &[u8; LENGTH16] = iv.as_slice().try_into().unwrap();
|
||||
let key: GenericArray<u8, _> = generate_generic_array(0, 1);
|
||||
let data = cbc::Encryptor::<aes::Aes128>::new(&key, iv.into())
|
||||
.encrypt_padded_vec_mut::<Pkcs7>("EncryptMe!".as_bytes());
|
||||
|
||||
let decrypted = super::decrypt_aes_128_cbc(&key, iv, &data).unwrap();
|
||||
|
||||
assert_eq!(String::from_utf8(decrypted).unwrap(), "EncryptMe!");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user