Why
/noise is classical X25519, so recorded sessions are open to harvest-now-decrypt-later. A hybrid KEM closes that, and stays secure if either primitive holds.
Proposal
A new, separately negotiated handshake (not a change to /noise), keeping the spec's "one id, one fixed suite" design:
- id:
/noise-mlkem768-hfs/0.1.0 (provisional)
- suite:
Noise_XXhfs_25519+ML-KEM-768_ChaChaPoly_SHA256. XX with Hybrid Forward Secrecy; ML-KEM-768 (FIPS 203) mixed into the chain alongside the X25519 DHs.
Identity payload and signature are unchanged. Authentication stays classical (it cannot be broken retroactively); only confidentiality is HNDL-sensitive.
Implementations advertise the hybrid id ahead of /noise, so a mixed fleet falls back with no flag day.
Reference impl
Working in Rust: libp2p/rust-libp2p#6481 over mcginty/snow#210. Revives #2168.
To pin for interop
- Protocol id string.
- Exact HFS token placement and KDF mixing order, with KATs, so go/js/rust agree byte for byte.
- ML-KEM-768 only, or the 512/768/1024 family?
Why
/noiseis classical X25519, so recorded sessions are open to harvest-now-decrypt-later. A hybrid KEM closes that, and stays secure if either primitive holds.Proposal
A new, separately negotiated handshake (not a change to
/noise), keeping the spec's "one id, one fixed suite" design:/noise-mlkem768-hfs/0.1.0(provisional)Noise_XXhfs_25519+ML-KEM-768_ChaChaPoly_SHA256. XX with Hybrid Forward Secrecy; ML-KEM-768 (FIPS 203) mixed into the chain alongside the X25519 DHs.Identity payload and signature are unchanged. Authentication stays classical (it cannot be broken retroactively); only confidentiality is HNDL-sensitive.
Implementations advertise the hybrid id ahead of
/noise, so a mixed fleet falls back with no flag day.Reference impl
Working in Rust: libp2p/rust-libp2p#6481 over mcginty/snow#210. Revives #2168.
To pin for interop