VERSION_BYTE = 0x02; v1 blobs rejected with UnsupportedFormatVersion; length-prefix Argon2 input distinguishes collision-engineerable pairs (audit H1 regression test). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
55 lines
1.7 KiB
Rust
55 lines
1.7 KiB
Rust
//! Format v2 invariants: VERSION_BYTE = 0x02, v1 blobs are rejected with
|
|
//! UnsupportedFormatVersion, length-prefix construction guarantees domain
|
|
//! separation.
|
|
|
|
use idfoto_core::{
|
|
IdfotoError,
|
|
crypto::{KdfParams, VERSION_BYTE},
|
|
decrypt, derive_master_key, encrypt,
|
|
};
|
|
use zeroize::Zeroizing;
|
|
|
|
fn fast_params() -> KdfParams { KdfParams { argon2_m: 256, argon2_t: 1, argon2_p: 1 } }
|
|
|
|
#[test]
|
|
fn version_byte_is_2() {
|
|
assert_eq!(VERSION_BYTE, 0x02);
|
|
}
|
|
|
|
#[test]
|
|
fn fresh_ciphertext_starts_with_0x02() {
|
|
let key = Zeroizing::new([0u8; 32]);
|
|
// encrypt(key: &[u8; 32], plaintext: &[u8])
|
|
let ct = encrypt(&*key, b"hello").unwrap();
|
|
assert_eq!(ct[0], 0x02);
|
|
}
|
|
|
|
#[test]
|
|
fn v1_blob_is_rejected_with_unsupported_format_version() {
|
|
// v1 layout: [0x01][24 nonce bytes][16 tag bytes]
|
|
let mut blob = vec![0x01u8];
|
|
blob.extend_from_slice(&[0u8; 24 + 16]);
|
|
let key = Zeroizing::new([0u8; 32]);
|
|
// decrypt(key: &[u8; 32], data: &[u8])
|
|
let err = decrypt(&*key, &blob);
|
|
match err {
|
|
Err(IdfotoError::UnsupportedFormatVersion { found, expected }) => {
|
|
assert_eq!(found, 0x01);
|
|
assert_eq!(expected, 0x02);
|
|
}
|
|
other => panic!("expected UnsupportedFormatVersion, got {other:?}"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn length_prefix_distinguishes_concat_collisions() {
|
|
let salt = [0u8; 32];
|
|
let img = [0x44u8; 32];
|
|
let p1 = b"abc";
|
|
let p2 = b"abcD"; // Pre-length-prefix, ("abc", [0x44, ...]) and ("abcD", ...)
|
|
// could be made to collide. With length-prefix they cannot.
|
|
let k1 = derive_master_key(p1, &img, &salt, &fast_params()).unwrap();
|
|
let k2 = derive_master_key(p2, &img, &salt, &fast_params()).unwrap();
|
|
assert_ne!(*k1, *k2);
|
|
}
|