test(core): integration tests for format v2 invariants
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>
This commit is contained in:
54
crates/idfoto-core/tests/format_v2.rs
Normal file
54
crates/idfoto-core/tests/format_v2.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
//! 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);
|
||||
}
|
||||
Reference in New Issue
Block a user