#![cfg(test)]
use super::*;
#[test]
fn every_issued_receipt_verifies_at_every_size_and_index() {
let key = primary();
let expected = key.public_key_bytes();
for size in 2..=33u64 {
for index in 0..size {
let path = path_of(size, index);
let leaf = leaf_bytes(index);
let receipt = sign_receipt(&leaf, index, size, &path, &key)
.unwrap_or_else(|e| panic!("issuance failed at size {size} index {index}: {e}"));
verify_receipt(&receipt, &leaf, &expected)
.unwrap_or_else(|e| panic!("verify failed at size {size} index {index}: {e}"));
let bytes = receipt.to_cose_bytes();
let parsed = verify_receipt_bytes(&bytes, &leaf, &expected).unwrap();
assert_eq!(parsed, receipt);
}
}
}
#[test]
fn the_signed_root_is_the_trees_own_root() {
let key = primary();
let size = 8;
let index = 3;
let tree = tree_of(size);
let receipt =
sign_receipt(&leaf_bytes(index), index, size, &path_of(size, index), &key).unwrap();
assert_eq!(
receipt.reconstructed_root(&leaf_bytes(index)).unwrap(),
tree.root().to_parts().0
);
}
#[test]
fn a_receipt_for_one_leaf_does_not_verify_for_another() {
let key = primary();
let size = 8;
let receipt = sign_receipt(&leaf_bytes(3), 3, size, &path_of(size, 3), &key).unwrap();
assert!(matches!(
verify_receipt(&receipt, &leaf_bytes(4), &key.public_key_bytes()),
Err(TrustError::ReceiptVerification)
));
let mut nearly = leaf_bytes(3);
nearly[0] ^= 0x01;
assert!(verify_receipt(&receipt, &nearly, &key.public_key_bytes()).is_err());
}
#[test]
fn a_receipt_from_an_unexpected_anchor_is_refused_though_it_is_internally_perfect() {
let attacker = other();
let size = 8;
let index = 3;
let leaf = leaf_bytes(index);
let receipt = sign_receipt(&leaf, index, size, &path_of(size, index), &attacker).unwrap();
verify_receipt(&receipt, &leaf, &attacker.public_key_bytes()).unwrap();
assert!(matches!(
verify_receipt(&receipt, &leaf, &primary().public_key_bytes()),
Err(TrustError::ReceiptVerification)
));
}
#[test]
fn swapping_the_embedded_anchor_key_breaks_the_signature_too() {
let key = primary();
let size = 8;
let index = 3;
let leaf = leaf_bytes(index);
let mut receipt = sign_receipt(&leaf, index, size, &path_of(size, index), &key).unwrap();
receipt.anchor_public_key = other().public_key_bytes();
assert!(verify_receipt(&receipt, &leaf, &other().public_key_bytes()).is_err());
}
#[test]
fn a_tampered_path_is_refused() {
let key = primary();
let size = 9;
let index = 4;
let leaf = leaf_bytes(index);
let expected = key.public_key_bytes();
for node in 0..path_of(size, index).len() {
for bit in [0x01u8, 0x80] {
let mut receipt =
sign_receipt(&leaf, index, size, &path_of(size, index), &key).unwrap();
receipt.inclusion_path[node][0] ^= bit;
assert!(
verify_receipt(&receipt, &leaf, &expected).is_err(),
"a flipped bit in path node {node} was accepted"
);
}
}
}
#[test]
fn reordering_the_path_is_refused() {
let key = primary();
let size = 16;
let index = 5;
let leaf = leaf_bytes(index);
let mut receipt = sign_receipt(&leaf, index, size, &path_of(size, index), &key).unwrap();
receipt.inclusion_path.reverse();
assert!(verify_receipt(&receipt, &leaf, &key.public_key_bytes()).is_err());
}
#[test]
fn a_tampered_leaf_index_is_refused() {
let key = primary();
let size = 16;
let leaf = leaf_bytes(5);
let mut receipt = sign_receipt(&leaf, 5, size, &path_of(size, 5), &key).unwrap();
receipt.leaf_index = 6;
assert!(verify_receipt(&receipt, &leaf, &key.public_key_bytes()).is_err());
}
#[test]
fn a_tampered_signature_is_refused() {
let key = primary();
let size = 8;
let index = 3;
let leaf = leaf_bytes(index);
for byte in [0usize, 31, 32, 63] {
let mut receipt = sign_receipt(&leaf, index, size, &path_of(size, index), &key).unwrap();
receipt.signature[byte] ^= 0x01;
assert!(verify_receipt(&receipt, &leaf, &key.public_key_bytes()).is_err());
}
}
#[test]
fn a_non_canonical_signature_scalar_is_refused() {
let key = primary();
let size = 8;
let index = 3;
let leaf = leaf_bytes(index);
let mut receipt = sign_receipt(&leaf, index, size, &path_of(size, index), &key).unwrap();
receipt.signature[63] |= 0xe0;
assert!(verify_receipt(&receipt, &leaf, &key.public_key_bytes()).is_err());
}
#[test]
fn a_receipt_cannot_be_replayed_against_a_different_tree() {
let key = primary();
let index = 3;
let leaf = leaf_bytes(index);
let receipt = sign_receipt(&leaf, index, 8, &path_of(8, index), &key).unwrap();
let mut replayed = receipt;
replayed.tree_size = 9;
replayed.inclusion_path = path_of(9, index);
assert!(verify_receipt(&replayed, &leaf, &key.public_key_bytes()).is_err());
}