use super::*;
fn identity(table_id: u64, bt: BlockType) -> BlockIdentity {
BlockIdentity {
table_id,
block_type: bt,
dict_id: 0,
window_log: 0,
}
}
#[test]
fn aad_len_matches_spec() {
assert_eq!(AAD_LEN, 23);
}
#[test]
fn magic_bytes_are_little_endian_for_skippable_frame() {
assert_eq!(MAGIC_METADATA_LE, [0x50, 0x2A, 0x4D, 0x18]);
assert_eq!(u32::from_le_bytes(MAGIC_METADATA_LE), 0x184D_2A50);
}
#[test]
fn header_byte_v1_packs_version_in_high_nibble() {
assert_eq!(HEADER_BYTE_V1, 0x10);
assert_eq!(HEADER_BYTE_V1 >> 4, FORMAT_VERSION_V1);
assert_eq!(HEADER_BYTE_V1 & 0x0F, 0);
}
#[test]
fn suite_nonce_lengths_match_registry() {
assert_eq!(SuiteId::Aes256Gcm.nonce_len(), 12);
assert_eq!(SuiteId::ChaCha20Poly1305.nonce_len(), 12);
}
#[test]
fn suite_id_byte_round_trip() {
for suite in [SuiteId::Aes256Gcm, SuiteId::ChaCha20Poly1305] {
assert_eq!(SuiteId::try_from(suite.as_byte()), Ok(suite));
}
}
#[test]
fn suite_id_rejects_unknown_byte() {
for byte in [0u8, 1, 4, 0x10, 0xFF] {
assert_eq!(SuiteId::try_from(byte), Err(byte));
}
}
#[test]
fn aad_layout_is_byte_exact_for_a_concrete_block() {
let ctx = EncryptionContext::v1(
0x55, SuiteId::ChaCha20Poly1305,
3, 0x05, );
let identity = BlockIdentity {
table_id: 0x1112_1314_1516_1718,
block_type: BlockType::Index, dict_id: 0xDEAD_BEEF,
window_log: 21,
};
let aad = build(&ctx, &identity);
assert_eq!(&aad[0..4], &[0x50, 0x2A, 0x4D, 0x18]);
assert_eq!(aad[4], 0x10);
assert_eq!(aad[5], 0x55);
assert_eq!(aad[6], 1);
assert_eq!(aad[7], 0x03);
assert_eq!(&aad[8..16], &0x1112_1314_1516_1718u64.to_be_bytes());
assert_eq!(aad[16], 3);
assert_eq!(&aad[17..21], &0xDEAD_BEEFu32.to_be_bytes());
assert_eq!(aad[21], 21);
assert_eq!(aad[22], 0x05);
}
#[test]
fn aad_for_zero_identity_is_well_formed() {
let ctx = EncryptionContext::v1(0, SuiteId::Aes256Gcm, 0, 0);
let id = identity(0, BlockType::Data);
let aad = build(&ctx, &id);
assert_eq!(aad.len(), AAD_LEN);
assert_eq!(&aad[0..4], &MAGIC_METADATA_LE);
assert_eq!(aad[4], HEADER_BYTE_V1);
assert_eq!(aad[5], 0); assert_eq!(aad[6], 0); assert_eq!(aad[7], 0x02); assert!(aad[8..].iter().all(|&b| b == 0));
}
#[test]
fn aad_changes_when_block_type_changes() {
let ctx = EncryptionContext::v1(1, SuiteId::Aes256Gcm, 0, 0);
let a = build(&ctx, &identity(2, BlockType::Data));
let b = build(&ctx, &identity(2, BlockType::Index));
assert_ne!(a, b);
assert_eq!(&a[..6], &b[..6]);
assert_eq!(&a[7..], &b[7..]);
}
#[test]
fn aad_changes_when_block_flags_changes() {
let a = build(
&EncryptionContext::v1(1, SuiteId::Aes256Gcm, 0, 0),
&identity(2, BlockType::Data),
);
let b = build(
&EncryptionContext::v1(1, SuiteId::Aes256Gcm, 0, 0x01),
&identity(2, BlockType::Data),
);
assert_ne!(a, b);
assert_eq!(&a[..22], &b[..22]);
assert_ne!(a[22], b[22]);
}