Skip to main content

qssm_utils/
hashing.rs

1//! Single source of truth for protocol domain strings (v1.0 hygiene).
2
3/// **Bump when** `qssm-le` `fs_challenge_bytes` input order or `public_binding_fs_bytes` serialization
4/// changes anything that gadget `TranscriptMap` / Engine A package JSON must mirror. Shared by `qssm-le`
5/// and `qssm-gadget` via this crate.
6pub const LE_FS_PUBLIC_BINDING_LAYOUT_VERSION: u32 = 1;
7
8pub const DOMAIN_MS: &str = "QSSM-MS-v1.0";
9pub const DOMAIN_LE: &str = "QSSM-LE-v1.0";
10/// Parent-node hashing for binary Merkle trees.
11pub const DOMAIN_MERKLE_PARENT: &str = "QSSM-MERKLE-PARENT-v1.0";
12/// SDK layer: derive MS seed from entropy seed + binding context.
13pub const DOMAIN_SDK_MS_SEED: &str = "QSSM-SDK-MS-SEED-v1";
14/// SDK layer: derive LE witness coefficients from entropy seed + binding context.
15pub const DOMAIN_SDK_LE_WITNESS: &str = "QSSM-SDK-LE-WITNESS-v1";
16/// SDK layer: derive LE masking CSPRNG seed from entropy seed + binding context.
17pub const DOMAIN_SDK_LE_MASK: &str = "QSSM-SDK-LE-MASK-v1";
18
19#[inline]
20pub fn blake3_hash(data: &[u8]) -> [u8; 32] {
21    *blake3::hash(data).as_bytes()
22}
23
24/// Domain-separated hash: `domain` as UTF-8 prefix, then each chunk in order.
25pub fn hash_domain(domain: &str, chunks: &[&[u8]]) -> [u8; 32] {
26    let mut h = blake3::Hasher::new();
27    h.update(domain.as_bytes());
28    for c in chunks {
29        h.update(c);
30    }
31    *h.finalize().as_bytes()
32}
33
34#[cfg(test)]
35mod tests {
36    use super::*;
37
38    #[test]
39    fn domain_tags_diverge_for_same_chunks() {
40        let chunk: &[u8] = b"shared-payload";
41        assert_ne!(
42            hash_domain(DOMAIN_MS, &[chunk]),
43            hash_domain(DOMAIN_LE, &[chunk])
44        );
45        assert_ne!(
46            hash_domain(DOMAIN_SDK_MS_SEED, &[chunk]),
47            hash_domain(DOMAIN_SDK_LE_WITNESS, &[chunk])
48        );
49        assert_ne!(
50            hash_domain(DOMAIN_SDK_LE_MASK, &[chunk]),
51            hash_domain(DOMAIN_MERKLE_PARENT, &[chunk])
52        );
53    }
54}