use sha2::{Digest, Sha256};
const DOMAIN: &[u8] = b"sealed-channel v1 transcript";
pub fn transcript_hash(client_hello: &[u8], server_challenge: &[u8]) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(DOMAIN);
hasher.update((client_hello.len() as u64).to_le_bytes());
hasher.update(client_hello);
hasher.update((server_challenge.len() as u64).to_le_bytes());
hasher.update(server_challenge);
hasher.finalize().into()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hash_is_deterministic() {
let a = transcript_hash(b"hello", b"challenge");
let b = transcript_hash(b"hello", b"challenge");
assert_eq!(a, b);
}
#[test]
fn length_prefix_prevents_ambiguity() {
let a = transcript_hash(b"ab", b"c");
let b = transcript_hash(b"a", b"bc");
assert_ne!(a, b);
}
#[test]
fn any_byte_change_changes_hash() {
let base = transcript_hash(b"client", b"server");
let flipped = transcript_hash(b"clienX", b"server");
assert_ne!(base, flipped);
}
}