use nahui::crypto::Vault;
const KEY: [u8; 32] = [0x42; 32];
const AAD: &[u8] = b"scrub-test";
fn peek_spare(v: &Vec<u8>, n: usize) -> Vec<u8> {
assert!(v.len() + n <= v.capacity());
let ptr = v.as_ptr();
unsafe {
let tail = std::slice::from_raw_parts(ptr.add(v.len()), n);
tail.to_vec()
}
}
#[test]
fn decrypt_into_scrubs_plaintext_on_auth_failure() {
let v = Vault::new(KEY);
let plaintext: Vec<u8> = (0u8..64).map(|i| 0x80 | i).collect();
let mut ct = v.encrypt(&plaintext, AAD).unwrap();
*ct.last_mut().unwrap() ^= 0xff;
let mut out: Vec<u8> = Vec::with_capacity(256);
let pre_len = out.len();
let ct_plaintext_len = ct.len() - 1 - 12 - 16;
assert!(v.decrypt_into(&ct, AAD, &mut out).is_err());
assert_eq!(out.len(), pre_len, "len must return to pre-call value");
let tail = peek_spare(&out, ct_plaintext_len);
assert!(
tail.iter().all(|&b| b == 0),
"spare capacity must be scrubbed; got {:02x?}",
&tail[..tail.len().min(16)]
);
}
#[test]
fn encrypt_into_on_success_leaves_only_ciphertext() {
let v = Vault::new(KEY);
let plaintext: Vec<u8> = (0u8..128).map(|i| 0xC0 | (i & 0x3F)).collect();
let mut out = Vec::with_capacity(512);
v.encrypt_into(&plaintext, AAD, &mut out).unwrap();
for win in out.windows(8) {
for pwin in plaintext.windows(8) {
assert_ne!(win, pwin, "plaintext leaked into ciphertext buffer");
}
}
}