DEV Community

Cover image for How to Prepare Your TLS Stack for Post-Quantum Cryptography Today
Alan West
Alan West

Posted on

How to Prepare Your TLS Stack for Post-Quantum Cryptography Today

If you've been ignoring the "quantum computing will break encryption" headlines for the last few years, I get it. It felt like a distant problem. But NIST finalized its first post-quantum cryptography standards in 2024, major browsers already support hybrid key exchange, and the timeline for "harvest now, decrypt later" attacks is... now. That's happening today.

So let's talk about what's actually breaking, why it matters for your services right now, and how to start migrating before you're scrambling.

The Problem: Your TLS Handshakes Have an Expiration Date

Here's the core issue. Most TLS connections today use key exchange algorithms like X25519 or ECDH (Elliptic Curve Diffie-Hellman). These rely on mathematical problems that classical computers can't efficiently solve — but quantum computers can, using Shor's algorithm.

The scary part isn't that quantum computers will break your encryption tomorrow. It's that adversaries are already recording encrypted traffic today, planning to decrypt it once quantum hardware catches up. This is called a "harvest now, decrypt later" (HNDL) attack, and it means any sensitive data you're transmitting over classical-only TLS has a shelf life.

If your data needs to stay confidential for 5+ years, this is already your problem.

What NIST Standardized (and What It Means for You)

In August 2024, NIST published three post-quantum cryptography standards:

  • ML-KEM (Module-Lattice-Based Key Encapsulation Mechanism, FIPS 203) — replaces classical key exchange
  • ML-DSA (Module-Lattice-Based Digital Signature Algorithm, FIPS 204) — replaces classical signatures
  • SLH-DSA (Stateless Hash-Based Digital Signature Algorithm, FIPS 205) — an alternative signature scheme

For TLS specifically, the most immediately relevant piece is ML-KEM, because protecting key exchange is the first defense against HNDL attacks. Signatures (ML-DSA) matter too, but an attacker who records traffic today can't retroactively forge a signature — they can retroactively decrypt the session.

That's why you're seeing hybrid key exchange roll out first across the ecosystem.

Step 1: Understand Hybrid Key Exchange

Nobody is ripping out classical crypto and going pure post-quantum overnight. The transition uses hybrid key exchange — combining a classical algorithm (like X25519) with a post-quantum one (like ML-KEM-768) in the same TLS handshake.

Why hybrid? If the post-quantum algorithm turns out to have an undiscovered weakness, you still have classical security. Belt and suspenders.

In practice, this looks like X25519MLKEM768 (sometimes written as X25519Kyber768Draft00 in older implementations before the final NIST standard). Check what your TLS library calls it:

# Check if your OpenSSL supports post-quantum key exchange
openssl s_client -connect example.com:443 -groups X25519MLKEM768 2>&1 | grep "Server Temp Key"

# If you're on an older OpenSSL, you might need the oqs-provider
# https://github.com/open-quantum-safe/oqs-provider
openssl list -kem-algorithms 2>/dev/null | grep -i ml-kem
Enter fullscreen mode Exit fullscreen mode

Step 2: Check Your TLS Library Support

Here's where things stand as of early 2026:

Library ML-KEM Support Notes
OpenSSL 3.5+ Yes (built-in) X25519MLKEM768 available natively
BoringSSL Yes Used by Chrome/Go; has supported hybrid PQ since late 2023
Go 1.23+ Yes crypto/tls supports X25519MLKEM768 by default
rustls Yes Via aws-lc-rs backend
NSS (Firefox) Yes Enabled in Firefox since ~v124

If you're running a Go service, you might already be negotiating post-quantum key exchange without realizing it. Go 1.23 enabled X25519MLKEM768 by default in crypto/tls.

Let's verify:

package main

import (
    "crypto/tls"
    "fmt"
    "net/http"
)

func main() {
    // Go 1.23+ negotiates X25519MLKEM768 by default
    // You can explicitly configure curve preferences if needed
    tlsConfig := &tls.Config{
        CurvePreferences: []tls.CurveID{
            tls.X25519MLKEM768, // hybrid post-quantum
            tls.X25519,          // classical fallback
        },
    }

    client := &http.Client{
        Transport: &http.Transport{
            TLSClientConfig: tlsConfig,
        },
    }

    resp, err := client.Get("https://pq.cloudflareresearch.com")
    if err != nil {
        fmt.Printf("Error: %v\n", err)
        return
    }
    defer resp.Body.Close()

    // Check the negotiated TLS version and key exchange
    state := resp.TLS
    fmt.Printf("TLS Version: %x\n", state.Version)
    fmt.Printf("Cipher Suite: %x\n", state.CipherSuite)
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Enable Post-Quantum on Your Servers

For nginx with OpenSSL 3.5+, the configuration is straightforward:

server {
    listen 443 ssl;

    ssl_protocols TLSv1.3;

    # Prefer hybrid PQ, fall back to classical
    # X25519MLKEM768 = hybrid post-quantum + classical
    ssl_ecdh_curve X25519MLKEM768:X25519:P-256;

    # Your existing cert and key work fine —
    # key exchange is independent of certificate signatures
    ssl_certificate     /etc/ssl/certs/your-cert.pem;
    ssl_certificate_key /etc/ssl/private/your-key.pem;
}
Enter fullscreen mode Exit fullscreen mode

Note something important: you do not need new certificates for hybrid key exchange. Your existing RSA or ECDSA certs work fine. The post-quantum upgrade here only affects the ephemeral key exchange, not the authentication step.

This is a huge deal — it means you can upgrade key exchange without touching your certificate infrastructure at all.

Step 4: Test and Monitor

After enabling hybrid key exchange, verify it's actually being used:

# Test with a client that supports PQ key exchange
openssl s_client -connect yourserver.com:443 -groups X25519MLKEM768 <<< "" 2>&1 | grep -E "Server Temp Key|Peer signing"

# Expected output includes something like:
# Server Temp Key: X25519MLKEM768, 1184 bits
Enter fullscreen mode Exit fullscreen mode

One thing to watch: hybrid handshakes are slightly larger than classical ones. The X25519MLKEM768 key share adds roughly 1,100 bytes to the ClientHello. In practice, I haven't seen this cause issues on modern networks, but if you're dealing with constrained MTU situations or very latency-sensitive UDP paths, it's worth measuring.

What About Signatures? (The Harder Problem)

Key exchange is the easy win. Post-quantum signatures (ML-DSA) are the harder migration because they affect your entire certificate chain — root CAs, intermediates, leaf certs, OCSP responses, all of it.

ML-DSA signatures are also significantly larger than ECDSA:

  • ECDSA P-256 signature: ~72 bytes
  • ML-DSA-65 signature: ~3,309 bytes
  • ML-DSA-65 public key: ~1,952 bytes

That's a non-trivial increase in handshake size when you multiply it across the certificate chain. The ecosystem is still working out how to handle this — approaches like certificate compression, Merkle tree certificates, and TLS trust expressions are all being explored.

For now, the practical advice: focus on key exchange first. That protects against HNDL attacks, which is the immediate threat.

Prevention: A Migration Checklist

Here's what I'd recommend doing this quarter:

  • Audit your TLS library versions. If you're still on OpenSSL 1.1.x, you need to upgrade regardless of quantum concerns.
  • Check if hybrid PQ is already enabled. If you're running Go 1.23+ or recent Chrome/Firefox, it probably is on the client side.
  • Enable hybrid key exchange on your servers. It's backward-compatible — clients that don't support it will fall back to classical.
  • Inventory long-lived secrets. Anything that needs to stay confidential for 5+ years should be transiting over PQ-protected connections.
  • Don't wait for the signature migration to start. Key exchange and signatures are independent upgrades. Do key exchange now.
  • Watch the IETF drafts. The standardization of PQ in TLS 1.3 is still evolving — keep an eye on draft-ietf-tls-hybrid-design and related work at the IETF.

The Bottom Line

Post-quantum migration isn't a future problem anymore. The standards are finalized, the libraries are shipping support, and harvest-now-decrypt-later is a real threat model. The good news is that the first step — hybrid key exchange — is genuinely easy to deploy. It's backward-compatible, it doesn't require new certificates, and most modern TLS libraries already support it.

The harder parts (post-quantum signatures, certificate chain migration) will take the ecosystem several more years to sort out. But there's no reason to wait on key exchange. Go update your nginx config. You'll sleep better.

Top comments (0)