Skip to main content

derive_sas_code

Function derive_sas_code 

Source
pub fn derive_sas_code(
    our_secret: &StaticSecret,
    their_public: &PublicKey,
    tx_id: &[u8; 16],
    our_mlkem_ek: Option<&[u8]>,
    their_mlkem_ek: Option<&[u8]>,
) -> Result<SasCode>
Expand description

Derive the 7-emoji + 3-group-decimal SAS code from the X25519 shared secret and the agreed-upon tx_id. Both peers compute this independently and must end up with the same answer for OOB comparison to succeed.

Matches the MSC 2241 SAS shape (not wire-compatible — see the module doc): HKDF-SHA256 with tx_id as salt and the SAS info string as info, expanded to 11 bytes. First 6 bytes → 7 6-bit chunks, rejection-sampled into 0..49 → emoji indices. Next 5 bytes → 3 13-bit chunks (+ 1000) → 3 four-digit decimal groups.

our_mlkem_ek / their_mlkem_ek are huddle 2.0’s optional post-quantum capability binding (see the module doc). The binding is gated on the partner’s key: pass their_mlkem_ek = Some(ek) when we hold the peer’s pinned ML-KEM encapsulation key, and our_mlkem_ek = Some(ek) for our own (always available for a 2.0 identity). Both eks are then folded into the HKDF info as domain-tag || SHA-256(sorted(our_ek, their_ek)), anchoring the pair’s PQ capability into the verified SAS so a relay can’t silently downgrade them to classical-only. Pass their_mlkem_ek = None for group members, pre-1.3 partners, or the classical fallback; that path is byte-for-byte identical to the 1.x derivation regardless of our_mlkem_ek. Because the eks are sorted, both peers derive the same code without needing to agree on an order.