use std::io::Cursor;
use wasm_bindgen_test::*;
use crate::crypto::{self, Error, STREAM_NONCE_LEN, TAG_LEN, VERSION, Vault};
wasm_bindgen_test_configure!(run_in_browser);
const AAD: &[u8] = b"file:upload";
fn vault() -> Vault {
Vault::new([0x42u8; 32])
}
fn fake_file(size: usize) -> Vec<u8> {
(0..size).map(|i| (i & 0xFF) as u8).collect()
}
#[wasm_bindgen_test]
fn browser_hash_and_encrypt_roundtrip() {
let file_bytes = fake_file(256 * 1024); let v = vault();
let mut encrypted = Vec::new();
let hash = v
.hash_and_encrypt_stream(&mut Cursor::new(&file_bytes), &mut encrypted, AAD)
.unwrap();
assert_eq!(hash.to_hex().len(), 64);
let mut decrypted = Vec::new();
v.decrypt_stream(&mut Cursor::new(encrypted), &mut decrypted, AAD)
.unwrap();
assert_eq!(file_bytes, decrypted);
}
#[wasm_bindgen_test]
fn browser_hash_is_of_plaintext_not_ciphertext() {
let file_bytes = fake_file(128 * 1024);
let v = vault();
let mut encrypted = Vec::new();
let got_hash = v
.hash_and_encrypt_stream(&mut Cursor::new(&file_bytes), &mut encrypted, AAD)
.unwrap();
assert_eq!(got_hash, crypto::hash_bytes(&file_bytes));
assert_ne!(got_hash, crypto::hash_bytes(&encrypted));
}
#[wasm_bindgen_test]
fn browser_nonces_are_random() {
let v = vault();
let msg = b"same plaintext".as_slice();
let mut ct1 = Vec::new();
let mut ct2 = Vec::new();
v.encrypt_stream(&mut Cursor::new(msg), &mut ct1, AAD)
.unwrap();
v.encrypt_stream(&mut Cursor::new(msg), &mut ct2, AAD)
.unwrap();
let header_range = 1..1 + STREAM_NONCE_LEN;
assert_ne!(&ct1[header_range.clone()], &ct2[header_range]);
assert_ne!(ct1, ct2);
}
#[wasm_bindgen_test]
fn browser_tampered_ciphertext_rejected() {
let v = vault();
let mut ct = Vec::new();
v.encrypt_stream(&mut Cursor::new(b"document".as_slice()), &mut ct, AAD)
.unwrap();
ct[1 + STREAM_NONCE_LEN] ^= 0xff;
let mut pt = Vec::new();
assert!(matches!(
v.decrypt_stream(&mut Cursor::new(ct), &mut pt, AAD),
Err(Error::AuthenticationFailed)
));
}
#[wasm_bindgen_test]
fn browser_wrong_key_rejected() {
let v = vault();
let mut ct = Vec::new();
v.encrypt_stream(&mut Cursor::new(b"document".as_slice()), &mut ct, AAD)
.unwrap();
let bad = Vault::new([0x00u8; 32]);
let mut pt = Vec::new();
assert!(matches!(
bad.decrypt_stream(&mut Cursor::new(ct), &mut pt, AAD),
Err(Error::AuthenticationFailed)
));
}
#[wasm_bindgen_test]
fn browser_wrong_aad_rejected() {
let v = vault();
let mut ct = Vec::new();
v.encrypt_stream(&mut Cursor::new(b"document".as_slice()), &mut ct, b"file:A")
.unwrap();
let mut pt = Vec::new();
assert!(matches!(
v.decrypt_stream(&mut Cursor::new(ct), &mut pt, b"file:B"),
Err(Error::AuthenticationFailed)
));
}
#[wasm_bindgen_test]
fn browser_empty_file_roundtrip() {
let v = vault();
let mut ct = Vec::new();
let hash = v
.hash_and_encrypt_stream(&mut Cursor::new(b"".as_slice()), &mut ct, AAD)
.unwrap();
assert_eq!(ct.len(), 1 + STREAM_NONCE_LEN + TAG_LEN);
assert_eq!(ct[0], VERSION);
let mut pt = Vec::new();
v.decrypt_stream(&mut Cursor::new(ct), &mut pt, AAD)
.unwrap();
assert!(pt.is_empty());
assert_eq!(hash.to_hex().len(), 64);
}
#[wasm_bindgen_test]
fn browser_large_file_roundtrip() {
let file_bytes = fake_file(3 * 1024 * 1024); let v = vault();
let mut ct = Vec::new();
let hash = v
.hash_and_encrypt_stream(&mut Cursor::new(&file_bytes), &mut ct, AAD)
.unwrap();
let mut pt = Vec::new();
v.decrypt_stream(&mut Cursor::new(ct), &mut pt, AAD)
.unwrap();
assert_eq!(file_bytes, pt);
assert_eq!(hash, crypto::hash_bytes(&file_bytes));
}