Post-Quantum Migration in 2026: What's Done, What's Stuck, and What to Do This Quarter

Sep 6, 2026 · 13 min · Ajay Kumar

Every few months a client asks me some version of "do we need to do anything about quantum yet". For years the honest answer was "inventory your crypto and wait". As of this quarter the answer has changed, and it changed for a mundane reason: the key-exchange half of the migration is finished in the software you already run, and the signature half is stuck on things no individual team can unstick.

This post is the state of play as I understand it on 6 September 2026, from the perspective of someone who runs TLS terminators, SSH bastions, and a certificate hierarchy for a living. It has three parts: what is already post-quantum whether you noticed or not, what is not and why, and the short list of things I would actually do before December. Every command below was run on my own machine this week. Every claim links to a primary source, and where I could only find secondary sources I say so.

Part 1: The key-exchange migration already happened

If you ran a TLS server in 2023 and updated your operating system since, there is a good chance your connections are already protected against a quantum adversary recording them today for decryption later. Nobody sent you a memo. It simply arrived in the default settings.

The mechanism is a hybrid key exchange, X25519MLKEM768, that combines classical elliptic-curve Diffie-Hellman with ML-KEM-768, the lattice-based key encapsulation mechanism NIST standardised as FIPS 203 in August 2024. Hybrid means an attacker has to break both. The IETF published the key-exchange construction as RFC 10024 last month, which is the point at which a thing stops being a draft everyone implements and becomes a standard everyone implements.

Here is where it is on by default:

Component Version Default behaviour Source
Chrome 131 (Nov 2024) Offers X25519MLKEM768 Google Security Blog
Firefox 132 (Oct 2024) Offers mlkem768x25519 Release notes
Apple platforms iOS/macOS 26 Advertises X25519MLKEM768 in ClientHello Apple support
OpenSSL 3.5 LTS (Apr 2025) Sends an ML-KEM key share in the default group list OpenSSL
OpenSSH 10.0 (Apr 2025) mlkem768x25519-sha256 is the default KEX Release notes
Go 1.24 (Feb 2025) X25519MLKEM768 enabled in crypto/tls Go 1.24 notes
Java JDK 27 (JEP 527) X25519MLKEM768 enabled and most preferred OpenJDK
Signal Oct 2025 ML-KEM-768 in the "triple ratchet" Signal blog

The aggregate effect is visible on the largest network that publishes numbers. Cloudflare reported over 50% of human-initiated traffic using post-quantum key agreement in October 2025, and over two-thirds of browser traffic by June 2026. They have a live dashboard. That is the client side. On the origin side, the share of servers that accept the hybrid group is much lower; Cloudflare's changelog describes it as roughly one in ten, though I could not confirm that exact figure in the page text and treat it as approximate.

You can check any endpoint you operate in one line. OpenSSL 3.5 or later:

openssl s_client -connect example.com:443 -groups X25519MLKEM768 -brief </dev/null

On a server that supports it, the output includes Negotiated TLS1.3 group: X25519MLKEM768. Leave off the -groups flag and you get the same result on a modern OpenSSL, because the default list already includes it. To see what your build knows about:

openssl list -kem-algorithms
openssl list -signature-algorithms

On my machine (OpenSSL 3.6.3) the first lists ML-KEM-512, 768 and 1024 plus the hybrids X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024 and X448MLKEM1024. The second lists ML-DSA-44, 65 and 87 and the SLH-DSA families. OpenSSL 4.0 shipped in April and adds more, but 3.5 is the LTS and supported until 2030, which is the one I run.

SSH is the same story:

ssh -Q kex

On OpenSSH 10.2 the list ends with sntrup761x25519-sha512 and mlkem768x25519-sha256, and the second is the default. If your bastion hosts are on 10.0 or later, and your clients are, your SSH sessions are already hybrid post-quantum. If you have pinned a KexAlgorithms line in sshd_config from a hardening guide written before 2025, you have probably turned this off. Go and look.

And if you write Go, the primitive is in the standard library. This compiles and prints the byte sizes that explain most of the engineering cost of this migration:

package main

import (
	"crypto/mlkem"
	"fmt"
)

func main() {
	dk, _ := mlkem.GenerateKey768()
	ekBytes := dk.EncapsulationKey().Bytes()

	ek, _ := mlkem.NewEncapsulationKey768(ekBytes)
	sharedA, ct := ek.Encapsulate()
	sharedB, _ := dk.Decapsulate(ct)

	fmt.Printf("ek=%d bytes ct=%d bytes shared=%d bytes match=%v\n",
		len(ekBytes), len(ct), len(sharedA), string(sharedA) == string(sharedB))
}

Output: ek=1184 bytes ct=1088 bytes shared=32 bytes match=true. Go 1.27, released last month, adds crypto/mldsa and ML-DSA support in crypto/x509, which brings us to the half that is not done.

Part 2: Signatures are stuck, and not on you

Key exchange protects against "harvest now, decrypt later": an adversary records your traffic today and decrypts it when they have the machine. That is why it went first. Signatures protect against forgery, which only matters once the machine exists, so there is less urgency and a lot more friction.

The friction is size. This chart is the entire problem in one picture.

KEY EXCHANGE (public key + ciphertext) X25519 64 B ML-KEM-768 2,272 B

SIGNATURE ONLY ECDSA P-256 64 B RSA-2048 256 B ML-DSA-44 2,420 B ML-DSA-65 3,309 B ML-DSA-87 4,627 B

Scale: 1 px ≈ 9.8 bytes. A typical TLS certificate chain carries 3 to 5 signatures plus 2 to 3 public keys.

Wire sizes from FIPS 203 and FIPS 204, as exposed by the Go crypto/mlkem and crypto/mldsa packages. ML-KEM-768 shows encapsulation key (1,184 B) plus ciphertext (1,088 B).

A key exchange adds about 2 KB to a handshake once, and ML-KEM computation is faster than X25519, so it was close to free. A certificate chain carries several signatures and public keys, and Cloudflare's measurement is that moving a median chain to ML-DSA-44 adds roughly 15 KB and slows non-resumed QUIC handshakes by about 15%. The larger ClientHello also breaks middleboxes that assumed it fits in one packet; Apple's support note warns about exactly this, and the tldr.fail class of bugs is why browsers rolled key exchange out so cautiously.

So the WebPKI is going a different way. In June, Let's Encrypt committed to Merkle Tree Certificates, a design where the certificate carries a short inclusion proof, around 800 bytes, against a signed tree head that browsers fetch out of band. Their timeline is a staging environment in late 2026 and production in 2027, and they note Chrome has said MTCs are its preferred path. The CA/Browser Forum minutes from May show an ML-DSA ballot still in development, with concerns about Certificate Transparency log sizes. The practical consequence for you: you cannot get a post-quantum public TLS certificate today, and you will not be able to until 2027 at the earliest. Nothing you do internally changes that.

What you can do today is post-quantum signatures where you control both ends:

  • X.509 for ML-DSA and ML-KEM is standardised: RFC 9881 and RFC 9935. Your internal PKI can issue ML-DSA certificates now. OpenSSL 3.5 and Go 1.27 will validate them.
  • Code and firmware signing: AWS KMS has supported ML-DSA since June 2025 and AWS Private CA does ML-DSA code signing. This is where NSA's CNSA 2.0 guidance asked for post-quantum first, because firmware signed today has to verify for a decade.
  • Composite signatures (classical plus ML-DSA in one) are still an IETF draft. If you want hybrid signing today you are choosing a draft.

Two NIST items are also less finished than the headlines suggest, and I want to be precise because I see them misreported. FIPS 206, the Falcon-derived FN-DSA standard, was described by NIST staff at their September 2025 conference as "basically written, awaiting approval", but as of this week the NIST page still lists it as in development and I could not find a published draft. HQC was selected in March 2025 as a backup KEM built on different mathematics, but I could not find a draft FIPS for it either. And NIST IR 8547, the document with the famous "deprecated after 2030, disallowed after 2035" timeline for RSA and ECC, is still the initial public draft from November 2024. The June 2026 federal memo cites it "or successor document". The dates are being treated as real. The document is not final.

Part 3: The deadlines are now real

For most of the past four years the mandates were aspirational. This summer they acquired dates and owners.

Authority Instrument Key dates
US federal Executive Order 14412 (22 Jun 2026) High-value systems on PQ key establishment by 31 Dec 2030; PQ signatures by 31 Dec 2031; contractors compliant with PQ FIPS by end of 2030
US federal OMB M-26-15 (24 Jun 2026) Migration plans due in 120 days; inventory 2026–27; pilots 2027–28; key establishment 2028–30; signatures 2031; full migration 2035
US national security CNSA 2.0 Software/firmware signing exclusively PQ by 2030; browsers, servers, cloud by 2033; all systems by 2035 (from secondary summaries; the NSA PDFs were not reachable when I checked)
EU Coordinated roadmap (23 Jun 2025) National plans and inventories started by end 2026; high-risk systems migrated by end 2030; as much as feasible by 2035
UK NCSC roadmap (20 Mar 2025) Identify and plan by 2028; high-priority upgrades 2028–31; complete by 2035

"Contractors compliant with PQ FIPS by end of 2030" is the line that will reach private companies that never thought of themselves as in scope. If you sell to a US federal agency, or to someone who does, that clause propagates through the supply chain the same way FedRAMP did.

Is the hardware urgency real?

I try to keep the hardware discussion short because it is the part most prone to hype, and because the deadlines above are policy facts regardless of physics. But the resource estimates moved this year and it is worth knowing by how much.

The reference point for a decade was that factoring RSA-2048 would need about 20 million noisy qubits running for eight hours. In May 2025 Craig Gidney revised that to under one million noisy qubits running for under a week, assuming 0.1% gate error rates. In March 2026 a Google team published a paper on elliptic-curve discrete logs estimating that breaking a 256-bit curve key, the kind that secures Bitcoin and most TLS, needs fewer than 500,000 physical qubits for a few minutes of runtime, and stated a 2029 migration target for their own systems.

Against that, the largest machines today: Google's Willow at 105 qubits, which in October 2025 demonstrated a verifiable advantage on a physics simulation; Quantinuum's Helios at 98 trapped-ion qubits with two-qubit fidelity above 99.9%, yielding 48 error-corrected logical qubits; a Caltech 6,100-atom array; and IBM's roadmap targeting 200 logical qubits in 2029. The gap between 100 physical qubits and 500,000 is enormous. The gap between 20 million and 500,000 in the requirement closed in twelve months, and that is the direction to watch. Nobody credible is claiming a cryptographically relevant machine exists. The policy dates are set on the assumption one could exist in the early-to-mid 2030s, and the requirement curve has only ever moved one way.

What I would do this quarter

Not a roadmap. A checklist that fits in a sprint.

  1. Verify key exchange is on, not assumed. Run the openssl s_client and ssh -Q kex checks above against your own endpoints. Grep your sshd_config, nginx, HAProxy and Envoy configs for pinned cipher and group lists that predate 2025. Every hardening guide from 2020 to 2024 is now a downgrade.
  2. Turn it on at the origin. Browsers already offer the hybrid group; most origins do not accept it. OpenSSL 3.5, Go 1.24, JDK 27 and current nginx and Envoy builds do. Your CDN probably already does. Your load balancer might not.
  3. Build the crypto inventory. OMB M-26-15 explicitly tells agencies to automate discovery. The format is CBOM in CycloneDX 1.6, and IBM's CBOMkit will scan code and containers. You will find RSA-1024 in a Java keystore somebody built in 2016. Everyone does.
  4. Move internal signatures where you own both ends. Internal CA, service mesh certificates, artifact signing, firmware. ML-DSA-65 is the sensible default. Test what it does to your handshake sizes and your Envoy config before you need to.
  5. Do not wait for public certificates. Watch Let's Encrypt's staging environment in late 2026. Nothing before then is actionable.
  6. Write the plan down. If you are in the EU, the roadmap wants a national-level inventory started by December. If you sell to the US government, someone is going to ask for yours by 2027. A two-page document beats a perfect one that does not exist.

The migration that seemed like a decade-long research project turned out to be two migrations. One of them happened in the defaults while nobody was looking. The other is waiting on a certificate ecosystem that will move in 2027. Your job this quarter is to make sure the first one actually reached your servers, and to have the inventory ready for the second.


Related: MCP Security in 2026 and The Worms Learned to Use Your AI Agent.

I'm Ajay Kumar — I build and operate PandaStack, an open-source Firecracker microVM cloud for AI agents. Everything above comes from running it in production.

Need this kind of infrastructure work? See what I do or email hello@ajayk.sh.


Related