Post-quantum key agreement
qrtc agrees the keys of DTLS 1.3 (media and data channels) and of TURN over TLS with hybrid X25519MLKEM768, the group browsers and TLS servers negotiate. A recording of today's traffic stays confidential even against a future quantum computer, as long as either half of the hybrid holds.
How a hybrid group works
Every group here is a key encapsulation mechanism (KEM) in the TLS 1.3 sense. The client sends an encapsulation key, the server answers with a ciphertext, and both derive the same secret. A hybrid group runs ML-KEM (FIPS 203) and X25519 side by side, following draft-ietf-tls-ecdhe-mlkem:
- client share: ML-KEM encapsulation key, then the X25519 public key;
- server share: ML-KEM ciphertext, then the X25519 public key;
- shared secret: the ML-KEM secret, then the X25519 secret.
Groups
| Group | Codepoint | Feature | Notes |
|---|---|---|---|
X25519MLKEM768 | 0x11ec | both | What browsers and TLS servers negotiate. Offered first. |
X25519MLKEM512 | 0xfe5c (private use) | pq-moduletto | NIST category 1 instead of 3. Only qrtc knows it; offered after 768, so only a peer without 768 picks it. Never used for TURN. |
MLKEM768 | 0x0201 | both | ML-KEM-768 alone. |
MLKEM512 | 0x0200 | pq-moduletto | ML-KEM-512 alone. DTLS only. |
Two ML-KEM backends
Both are pure Rust and differ only in where ML-KEM comes from:
pq-moduletto, the default: moduletto, CrabNebula's ML-KEM-512 and ML-KEM-768 with NEON on aarch64. It passes every NIST ACVP vector, including the key-check groups, and decapsulates RustCrypto's output and the reverse.pq-hybrid: RustCrypto ml-kem, for ML-KEM-768.
With both features on, moduletto wins.
Policies
Each connection picks a policy with RtcConfiguration::post_quantum (postQuantum in JSON). Without one, the engine uses prefer when built with a post-quantum feature and off otherwise.
| Policy | DTLS | TURN over TLS |
|---|---|---|
off | DTLS 1.2, classical groups | Classical groups |
prefer | Auto-senses the version: DTLS 1.3 with X25519MLKEM768 when the peer supports it, DTLS 1.2 otherwise | X25519MLKEM768 and MLKEM768 first, classical groups after |
require | DTLS 1.3 with post-quantum groups only | TLS 1.3 with post-quantum groups only |
Under prefer, the ClientHello offers DTLS 1.2 and 1.3 with the hybrid share, and the peer's answer decides the version. When qrtc is the DTLS server, the peer's ClientHello decides. Setting a policy other than off without a post-quantum feature is a NotSupportedError.
What had to change in DTLS
str0m's DTLS library, dimpl, knew only Diffie-Hellman groups. qrtc vendors it with six patches, all meant for upstream (details):
- Named groups. ML-KEM and hybrid codepoints, and a supported-groups list that grows from 4 to 10 entries.
- Server-side key exchange in one step. A KEM server cannot produce its share before it has the client's, because its share is a ciphertext for the client's key.
- KEM groups kept out of DTLS 1.2, where the server sends its share first.
- Provider validation that exercises both kinds of group.
- Fragmented ClientHello. A hybrid ClientHello is about 1.4 kB, above the DTLS MTU, so it is split into MTU-sized records (RFC 9147 section 5.5).
- Fragmented ServerHello detection. A ServerHello split over several records carries a large key share, so it is DTLS 1.3.
Seeing the result
stats() reports the negotiated group as the transport's tlsGroup, for example "X25519MLKEM768". It is absent after a classical DTLS 1.2 handshake.
Interoperability
| Peer | Result |
|---|---|
| qrtc, every policy pair, both backends | Unit tests: require fails against off, every other pair connects, with a hybrid group whenever both sides have one |
Chromium 141 with WebRTC-ForceDtls13 and WebRTC-EnableDtlsPqc | DTLS 1.3 with X25519MLKEM768, both offer directions, under prefer and require |
| Chromium 141 without flags | DTLS 1.2 under prefer; no connection under require |
| OpenSSL 3.5 TLS server accepting only X25519MLKEM768 | TURN over TLS connects with both backends and both rustls providers |
CI runs the Chromium and OpenSSL checks on every push; see Testing and CI.