ML-KEM-768 Explained: The Quantum-Safe Algorithm in Every QuickZTNA Tunnel
ML-KEM-768 is the NIST-standardised post-quantum key encapsulation mechanism behind every QuickZTNA WireGuard tunnel. Here is how it works, how fast it is, and why we pair it with X25519 by default.
TL;DR
ML-KEM-768 is the NIST-standardised post-quantum key encapsulation mechanism published as FIPS 203 on August 13, 2024. It is derived from CRYSTALS-Kyber and based on the hardness of the Module Learning With Errors problem. In QuickZTNA, every WireGuard tunnel uses ML-KEM-768 in a hybrid combination with X25519, so that breaking a tunnel requires breaking both a post-quantum lattice scheme and a classical elliptic-curve scheme. A public key is 1,184 bytes, a ciphertext is 1,088 bytes, and a shared secret is 32 bytes. Encapsulation and decapsulation each run in well under a millisecond on commodity hardware. This post explains how ML-KEM-768 works, how we use it, and what to ask other vendors before you trust their “quantum-safe” marketing.
Who this is for
Security engineers, platform teams, and compliance leads who want a technical, non-handwavy explanation of what sits inside a modern post-quantum key exchange. We assume you are comfortable reading a bit of code and are familiar with TLS or WireGuard at a glance. Cryptographers writing security proofs should read the primary sources instead — this post is for builders and buyers.
Table of contents
- Why a new KEM at all
- What “ML-KEM-768” actually stands for
- The three things a KEM does
- Size budget: bytes on the wire
- Security levels and how to choose
- ML-KEM vs Kyber: what changed during standardisation
- Hybrid mode: X25519 + ML-KEM-768
- How ML-KEM-768 is wired into QuickZTNA
- Benchmarks: CPU and wire time
- Implementation choices and common pitfalls
- Compliance posture: CNSA 2.0, BSI, ANSSI
- What to ask your vendor
- Further reading
1. Why a new KEM at all
Every transport-layer security protocol in wide use in 2026 — TLS 1.3, SSH, IPsec, WireGuard — relies on a Diffie-Hellman-style key exchange to agree on a symmetric session key. The two dominant variants are finite-field Diffie-Hellman, which you will see on the wire as RFC 7919 groups, and elliptic-curve Diffie-Hellman, which in practice means X25519 for modern protocols.
Both classical variants rely on hardness assumptions that fall to a sufficiently large quantum computer running Shor’s algorithm. The concrete quantum requirement is more than a billion error-corrected logical qubits for a general-purpose attack on X25519, which no one has built and no roadmap publicly projects before the late 2030s. That fact seduces people into thinking the problem is far away.
It is not. Traffic captured today can be decrypted later, once a capable machine exists. The pattern has a name: harvest now, decrypt later. If the data you are sending today will still be sensitive in 2040 — trade secrets, long-term regulatory submissions, health records, banking records — then your current TLS or WireGuard session is already leaking. The adversary does not need a quantum computer yet. They need a hard drive.
The response from the cryptographic community has been a decade-long competition, run by NIST, to standardise post-quantum replacements. The winners from the key-encapsulation track are the ML-KEM family. ML-KEM-768 is the middle parameter set and the one we recommend as a reasonable default for commercial traffic.
2. What “ML-KEM-768” actually stands for
The name has three parts.
- ML-KEM is “Module-Lattice-based Key-Encapsulation Mechanism”. The mathematical machinery lives in polynomial rings over integers mod a small prime, and the hard problem is a structured version of the Learning With Errors problem called Module-LWE.
- -768 is the dimension-like parameter that drives security level. The three standardised parameter sets are 512, 768, and 1024, which map to NIST security categories 1, 3, and 5. We explain categories below.
- FIPS 203 is the NIST standard document. Published August 13, 2024. Read it when you need to implement: csrc.nist.gov/pubs/fips/203/final.
If you come across a document, library, or vendor claim still using the names “Kyber”, “Kyber-768”, or “CRYSTALS-Kyber” in 2026, treat that as a warning sign to look harder. Kyber was the name through the NIST competition; ML-KEM is the standardised version with non-trivial differences. A library that has not been updated in two years may still be shipping pre-standardised Kyber, which is not interoperable with ML-KEM implementations.
3. The three things a KEM does
A key-encapsulation mechanism is a simpler concept than a full key-exchange protocol. It exposes three operations.
KeyGen() -> (public_key, secret_key)
Encapsulate(public_key) -> (ciphertext, shared_secret)
Decapsulate(secret_key, ciphertext) -> shared_secret
A typical tunnel handshake uses it like this. The responder runs KeyGen and sends its public key to the initiator. The initiator runs Encapsulate against that public key and sends the ciphertext back. Both sides now hold the same 32-byte shared secret, which they feed into a key derivation function and then into their symmetric cipher suite. It looks almost exactly like an ephemeral Diffie-Hellman exchange from the outside, except the shape and size of the messages are different.
There is one subtle but important property: ML-KEM is IND-CCA2 secure. That means even an adversary who can persuade a decapsulation oracle to decapsulate arbitrary ciphertexts cannot recover the secret key or break the one session they target. This matters because it lets a responder reuse a single long-lived ML-KEM key pair across many encapsulations without losing security, although ephemeral keys are still the default for forward secrecy. All ML-KEM ciphertexts are unique due to internal randomness.
4. Size budget: bytes on the wire
For ML-KEM-768, the byte sizes are fixed by the standard.
| Artefact | Bytes |
|---|---|
| Public key | 1,184 |
| Secret key | 2,400 |
| Ciphertext | 1,088 |
| Shared secret | 32 |
Compare that to X25519.
| Artefact | Bytes |
|---|---|
| Public key | 32 |
| Private scalar | 32 |
| Shared secret | 32 |
ML-KEM-768 is about 37× larger on the wire for the public key and 34× larger for the ciphertext. A hybrid X25519 + ML-KEM-768 handshake carries an extra 2,272 bytes compared to X25519 alone (1,184 + 1,088). In most TCP and UDP environments that is a small hit. It does cross some legacy MTU boundaries and QUIC packet thresholds, which is the main reason vendors historically delayed rollout. Modern MTUs handle it fine; legacy middleboxes sometimes do not.
If you care about the bandwidth: one ML-KEM-768 handshake per peer per rekey. WireGuard rekeys every two minutes by default. An always-on mesh of 100 peers that all rekey on schedule transfers about 36 MB per day in extra handshake bytes. Negligible at today’s network prices.
5. Security levels and how to choose
NIST defined five security categories for the post-quantum competition, anchored to well-known symmetric primitives.
| Category | Classical strength reference | ML-KEM parameter |
|---|---|---|
| 1 | At least as hard to break as AES-128 via exhaustive key search | ML-KEM-512 |
| 3 | At least as hard to break as AES-192 via exhaustive key search | ML-KEM-768 |
| 5 | At least as hard to break as AES-256 via exhaustive key search | ML-KEM-1024 |
You rarely have to agonise over the choice.
- ML-KEM-512 is defensible where bandwidth is very scarce, such as some IoT links, and when the data being protected has a short lifetime.
- ML-KEM-768 is the sensible default for commercial use. It is the level specified in TLS 1.3 hybrid drafts, the level shipped by default in most browser-to-cloud deployments, and the level chosen in QuickZTNA.
- ML-KEM-1024 is what the NSA’s CNSA 2.0 guidance picks for US national security systems. If you are specifically targeting NSS compliance, use it. For everyone else, the marginal security gain over 768 is not worth the bandwidth and CPU, given that 768 already exceeds AES-192 classical strength.
Note: CNSA 2.0 specifies ML-KEM-1024 rather than 768. QuickZTNA ships 768 as the default and plans to add a 1024 opt-in for customers with CNSA-aligned policies as part of a 2026-Q3 release. We will not describe that release as “CNSA 2.0 compliant” until the full algorithm suite is in place and validated.
6. ML-KEM vs Kyber: what changed during standardisation
During the four-year NIST process, the CRYSTALS-Kyber submission went through rounds of comment and tightening. The final standard published as FIPS 203 is not bit-compatible with the intermediate Kyber drafts. The main differences you need to know about:
- Domain separation in the key derivation function. ML-KEM hashes the public key into the seed that generates the internal randomness used during encapsulation. This prevents a class of multi-target attacks.
- Implicit rejection value derivation. In Kyber, the “implicit rejection” response for a malformed ciphertext was derived differently. ML-KEM fixed the procedure to avoid a potential variant of the FO transform ambiguity.
- Deterministic encapsulation API. FIPS 203 specifies a deterministic KeyGen that accepts a seed, simplifying known-answer testing and FIPS 140-3 validation.
Practical implication: if you have code that uses a pre-standard Kyber library from 2022 or 2023, you cannot interoperate with a peer running ML-KEM. You must upgrade. Every major language has a standards-conformant implementation today. The Go 1.24 standard library, which QuickZTNA uses, exposes ML-KEM-768 through the crypto/mlkem package.
7. Hybrid mode: X25519 + ML-KEM-768
You do not have to choose between classical and post-quantum. The industry consensus during the transition is to use a hybrid key exchange that combines both, so that the resulting session key is secure if either underlying primitive holds.
In QuickZTNA the construction is:
(classical_pk, classical_sk) = X25519_KeyGen()
(pq_pk, pq_sk) = ML_KEM_768_KeyGen()
classical_shared = X25519(classical_sk, peer_classical_pk)
(pq_ct, pq_shared) = ML_KEM_768_Encap(peer_pq_pk)
session_secret = HKDF-SHA256(
IKM = classical_shared || pq_shared,
salt = handshake_transcript,
info = "quickztna-pqc-wg-psk-v1",
len = 32
)
The combined secret is then used as the WireGuard pre-shared key. This gives you five properties at once.
- Classical confidentiality. If ML-KEM is broken by some unknown lattice attack, the X25519 component still protects the session.
- Post-quantum confidentiality. If a sufficiently large quantum computer appears and breaks X25519, the ML-KEM component still protects the session.
- Forward secrecy. Both key pairs are ephemeral per handshake, so compromise of long-term identity keys does not compromise past sessions.
- Transcript binding. The handshake transcript is folded into the KDF salt, so man-in-the-middle attempts that rewrite other fields invalidate the derived secret.
- Domain separation. The
infostring in HKDF makes the derived key unusable in any other context.
The same structure — ephemeral classical, ephemeral post-quantum, hybrid combiner — is what the IETF is standardising for TLS 1.3 in draft-ietf-tls-hybrid-design and what Cloudflare and AWS have already shipped on the public internet for their respective edge networks.
8. How ML-KEM-768 is wired into QuickZTNA
QuickZTNA is a ZTNA mesh built on WireGuard. Every peer-to-peer tunnel is a standard WireGuard session, with the twist that the pre-shared key field is populated from a hybrid X25519 + ML-KEM-768 handshake rather than left empty or statically configured.
The flow in production:
- When a new peer relationship is established, both sides generate ephemeral X25519 keys and ephemeral ML-KEM-768 keys.
- The coordination server relays the public halves between peers. It never sees the private halves.
- Each peer runs the hybrid derivation above and stores the resulting 32-byte value as the WireGuard PSK for that tunnel.
- The WireGuard engine uses the PSK as part of its existing Noise handshake, layered on top of its own Curve25519 static-key exchange.
- Every two minutes, WireGuard rekeys. QuickZTNA re-runs the hybrid handshake on a configurable cadence so the PSK itself rotates rather than becoming stale.
Because the PQC PSK is layered under the normal WireGuard handshake, a peer that does not support post-quantum (older client, third-party WireGuard) still connects; it just falls back to classical-only security. That degradation is explicit and visible in the peer’s status line. You can see the mixed state on the dashboard at login.quickztna.com when a tunnel is marked “classical-only”.
For code, the relevant packages in the client are:
pkg/crypto/pqc.go— ML-KEM-768 keygen, encap, decap, and PSK derivation. Uses thecrypto/mlkemstandard library type.pkg/agent/pqc.go— per-peer state machine. Caches derived PSKs. Handles rekey.pkg/wireguard/engine.go— injects the PSK into the WireGuard IPC. ThePresharedKeyHexfield on the peer struct is how it crosses into wireguard-go.
The post-quantum section of the QuickZTNA docs describes the exact packet layout for anyone implementing a compatible client.
9. Benchmarks: CPU and wire time
Here are real numbers on a 2022 Lenovo ThinkPad X13 Gen 3, Intel Core i7-1260P, running Go 1.24 on Linux 6.11 with GODEBUG=fips140=on disabled (we are measuring the vanilla standard library).
// go test ./pkg/crypto/... -bench=. -benchmem
BenchmarkMLKEM768KeyGen-16 12890 91274 ns/op 8432 B/op 12 allocs/op
BenchmarkMLKEM768Encap-16 11934 100431 ns/op 7616 B/op 10 allocs/op
BenchmarkMLKEM768Decap-16 15732 76210 ns/op 3392 B/op 6 allocs/op
BenchmarkX25519Scalar-16 157923 7590 ns/op 0 B/op 0 allocs/op
Translated: ML-KEM-768 keygen is about 91 microseconds, encap is 100 microseconds, decap is 76 microseconds. X25519 is about 12× faster per operation. That sounds bad in relative terms and turns out to be irrelevant in absolute terms, because:
- A WireGuard rekey happens every 120 seconds.
- An always-on mesh generates roughly one handshake per peer per 120 seconds.
- Even 100 peers rekeying simultaneously is 100 × 91µs = 9.1 ms of aggregate CPU time per cycle.
On the wire, the extra 2,272 bytes of hybrid handshake traffic cost 0.18 ms on a 100 Mbit link and 18 microseconds on a 1 Gbit link. In practice we have never seen a measurable user-visible latency from the PQC component on any production network.
10. Implementation choices and common pitfalls
Ten things to verify when you ship ML-KEM-768 yourself.
- Use a standards-conformant library. Go 1.24
crypto/mlkem, OpenSSL 3.5, BoringSSL main branch, libOQS, AWS-LC, and Microsoft’s SymCrypt all have conformant implementations. Pre-FIPS-203 Kyber libraries do not interoperate; discard them. - Do not try to write your own polynomial multiplication. The NTT routines are subtle, and constant-time failures here leak key material. Use the vetted library.
- Encapsulation randomness must come from a strong CSPRNG. ML-KEM’s IND-CCA2 proof depends on good randomness at encapsulation time. On Linux use
getrandom(2). Never userand(). - Feed the full public key into the KEM, not a hash. Some hobbyist libraries hash the public key first to save space. This breaks standard compliance and interoperability.
- Compose the hybrid secret by concatenation, then KDF. Simple XOR is wrong because it leaks structure. Full-length concatenation of both shared secrets, followed by HKDF with a fixed info string, is the documented construction.
- Include a transcript in the KDF. We fold the handshake transcript into the HKDF salt. Without it you are vulnerable to a class of re-routing attacks.
- Validate public keys at the deserialisation boundary. FIPS 203 specifies that encapsulators must check that the public key decodes to valid polynomial coefficients. A buggy decoder can be used as an oracle.
- Do not reuse nonces across rekey. ML-KEM itself has no nonces; this is about the AEAD used afterwards. But a common mistake is to keep the AEAD key constant across rekey; rotate it.
- Keep a compile-time flag for classical-only fallback. Operators sometimes have to disable PQC to interoperate with stale peers. Make it loud and logged, not silent.
- Log the key exchange mode in your session table. You want to grep through logs later and prove what crypto protected which session. We log
kex=hybrid-x25519-mlkem768on every established tunnel.
11. Compliance posture: CNSA 2.0, BSI, ANSSI
Three governments, three recommendations, broadly aligned.
NSA CNSA 2.0 (United States)
The Commercial National Security Algorithm Suite 2.0, published by the NSA in September 2022, specifies ML-KEM-1024 (not 768) for key establishment and ML-DSA-87 for digital signatures in National Security Systems. The transition timeline, laid out in later CSA memoranda, sets multi-year deadlines per system class. See our CNSA 2.0 deadlines post for the specifics. If you are selling into DoD systems, you need the 1024 parameter set.
BSI (Germany)
The Bundesamt für Sicherheit in der Informationstechnik publishes TR-02102-1, its cryptographic key-length recommendations, updated annually. The 2025 revision recommends hybrid classical-plus-post-quantum key establishment for applications where confidentiality of data must be protected beyond 2030, and names ML-KEM among the acceptable post-quantum mechanisms. For our walkthrough of what this means in practice, see BSI TR-02102-1 and Post-Quantum.
ANSSI (France)
The Agence nationale de la sécurité des systèmes d’information has been publishing PQC transition views since 2022. The current position is a three-phase transition: hybrid deployments during the late 2020s, standalone PQC acceptable after wider ecosystem maturity, and a requirement for hybrid for any new system with long-lived confidentiality requirements. Our detailed walkthrough is in ANSSI PQC Transition Plan.
The key observation: all three agencies recommend hybrid today, and all three name the ML-KEM family as an acceptable post-quantum component. A system that ships hybrid X25519 + ML-KEM-768 today is already aligned with the current recommendations of the three largest Western cybersecurity agencies.
12. What to ask your vendor
If a vendor says their product is “quantum-safe” or “post-quantum ready”, these are the questions that separate marketing from engineering.
- What algorithm specifically, at what parameter set? The honest answer names ML-KEM-768 or ML-KEM-1024. Fuzzy answers like “lattice-based” or “NIST-approved” are a warning.
- Is it hybrid or PQ-only? Hybrid is the right answer today. PQ-only means the vendor has not thought about unknown future lattice cryptanalysis.
- Pre-standard Kyber or ML-KEM? If the vendor has not updated their crypto library since the 2024 standard, they are shipping something that will not interoperate.
- What is the PSK source? If the vendor just mixes a PQC secret into a key derivation step without rotating it, their forward secrecy claim is weaker than it sounds.
- How often does the PQ key rotate? We rotate every WireGuard rekey, i.e. every two minutes. If they do not rotate, ask why.
- Can you see the mode on the wire? We log it. An operator should be able to prove which sessions were protected by which key exchange.
- What happens if a peer does not support PQC? Hard failure? Silent downgrade? Logged downgrade? Silent downgrade is the worst answer.
- Has the implementation been independently audited? Not “self-audited”. An external firm or a published peer-reviewed paper. Bonus points for in-scope implementation fuzzing.
- Is it on by default or opt-in? Opt-in is a red flag. The whole point of a harvest-now-decrypt-later defence is that it is on when the attacker is capturing.
- How is the configuration exposed? Can operators disable it in an emergency? Is that change logged and audited?
QuickZTNA answers: ML-KEM-768, hybrid with X25519, FIPS 203 conformant via Go 1.24 stdlib, PSK from HKDF of both shared secrets with transcript binding, rotated every two minutes, visible per-tunnel in the dashboard, hard-requires one end of the conversation to be a compatible client, on by default on every plan including Free, disable only via org-policy with audit event. We are happy to be asked any of these questions — and we encourage you to ask our competitors too.
13. Further reading
Primary sources first, secondary reading after. All links verified on the publish date.
- FIPS 203 — Module-Lattice-Based Key-Encapsulation Mechanism Standard. The standard itself. Read sections 1–3 for context, then section 7 for the parameter sets.
- NIST IR 8528 — Analysis of the Quantum-Resistant Algorithms. Background on the selection process.
- IETF draft-ietf-tls-hybrid-design. How the industry is wiring hybrid KEMs into TLS 1.3.
- NSA CSI, “Announcing the Commercial National Security Algorithm Suite 2.0”. The US defence roadmap.
- Go
crypto/mlkemdocumentation. The API we use. - QuickZTNA security docs. Exact packet layout and test vectors for our hybrid scheme.
Related reading on this blog
- Harvest Now, Decrypt Later: Why Your VPN Traffic Is Already Compromised
- Hybrid Key Exchange: X25519 + ML-KEM-768 in 800 Words
- NSA CNSA 2.0: Every Deadline Every DoD Contractor Needs to Know
Try QuickZTNA
ML-KEM-768 is not a feature gate. Every QuickZTNA tunnel — on every plan, including the Free tier — runs hybrid X25519 + ML-KEM-768 by default. Start a free account, add a peer, and run ztna status to see the exact key exchange mode reported for each tunnel. If you need ML-KEM-1024 for CNSA 2.0 alignment, contact sales — it is on the 2026-Q3 roadmap.
Frequently asked questions
Is ML-KEM-768 the same as Kyber?
ML-KEM is derived from CRYSTALS-Kyber but is not identical. NIST made several changes during standardisation, including a domain-separated KDF and a different way of deriving the rejection value for implicit rejection. Any library that claims to implement FIPS 203 should implement the ML-KEM variant, not plain Kyber.
What security level does ML-KEM-768 provide?
ML-KEM-768 is NIST security category 3, intended to be at least as hard to break as recovering a 192-bit AES key via exhaustive search. It is the middle of the three parameter sets (category 1, 3, and 5). Category 3 is sufficient for any commercial use case we are aware of in 2026.
Why use X25519 + ML-KEM-768 as a hybrid instead of ML-KEM-768 alone?
Defence in depth. ML-KEM is a new standard and the body of cryptanalysis against it is a few years old. Pairing it with X25519 means an attacker has to break both a lattice-based scheme and an elliptic-curve scheme to recover the session key. If either holds, you are safe. Hybrid is also what the NSA CNSA 2.0 transition guidance, the German BSI, and the French ANSSI all recommend for the migration window.
How much does ML-KEM-768 slow down a WireGuard handshake?
On a 2022-era laptop, ML-KEM-768 keygen, encap, and decap each complete in well under a millisecond. The dominant cost is the 1,088-byte ciphertext that now travels in the handshake, not the CPU. On a 100 Mbit link, the extra bytes add roughly 100 microseconds of wire time. In QuickZTNA we measure total hybrid handshake overhead at under 5 ms end-to-end.
Is ML-KEM-768 FIPS 140-3 certified?
ML-KEM is standardised as FIPS 203. Individual implementations need separate FIPS 140-3 validation through the CMVP programme. As of April 2026 several vendors have submitted ML-KEM modules for validation; NIST maintains the current list on the Cryptographic Module Validation Program site. QuickZTNA uses the Go 1.24 standard library implementation, which is not FIPS-validated on its own.
When will NIST require ML-KEM for federal systems?
There is no single switch. The NSA's CNSA 2.0 roadmap sets transition deadlines per technology class, with the latest dates falling between 2030 and 2035 depending on system type. Non-federal organisations are not required to switch, but regulators in the EU, Germany, and France have all published guidance recommending that long-lived data be protected with post-quantum cryptography starting now.