Quantum-Safe OpenSSH and OpenSSL
Quantum computer in a data center, yes this image was AI-generated.
In my last post on Quantum Readiness, I talked a bit about Q-Day, the "harvest now, decrypt later" threat, and threw out a Python script I wrote to check live systems like HTTPS and SSH to see if they are actually using post-quantum cryptography (PQC).
It’s one thing to test your systems and see that they are relying entirely on legacy algorithms. It’s an entirely different thing to roll up your sleeves and actually fix the configurations. Since the main services I care about on my home Ubuntu servers are SSH and HTTPS, I figured it made sense to outline exactly how to configure OpenSSH and NGINX to handle the incoming quantum threat.
For this walkthrough, I’m jumping straight to the good stuff. We are bypassing the older experimental plugins and defaulting to the modern, bleeding-edge stacks: OpenSSH 9.9+ and OpenSSL 3.5+. These versions have native, out-of-the-box support for the finalized NIST standards, meaning we can do pure PQC.
The approach you take really depends on your environment. For most folks, a hybrid approach—where you support quantum-safe algorithms but fall back to traditional encryption for older clients—is the way to go. If you are running a highly sensitive, isolated network and want to force the issue, you can go strictly post-quantum. Here is how to do both.
Securing OpenSSH
The OpenSSH developers have been way ahead of the curve on this. While OpenSSH 9.0 introduced an early hybrid approach using NTRU Prime, version 9.9 integrated the official NIST-standardized ML-KEM algorithm, which became the default in version 10.0.
This means that by default modern OpenSSH will try to do the right thing, but we want to explicitly declare our cipher preferences in ‘/etc/ssh/sshd_config’.
Option 1: Quantum-Safe but Backward Compatible (Hybrid)
This is what I recommend for almost everyone. It tells your server to prefer the shiny new NIST ML-KEM hybrid algorithm (`mlkem768x25519-sha256`) first. If the client doesn't support it, it drops down to the older NTRU hybrid, and finally down to standard, robust traditional curves like Curve25519.
KexAlgorithms mlkem768x25519-sha256,sntrup761x25519-sha512@openssh.com,curve25519-sha256,curve25519-sha256@libssh.orgOption 2: Strict Quantum-Safe Only
If you are running a tightly controlled lab or enterprise environment and you know for an absolute fact that every client connecting is running a modern OpenSSH client, you can drop the legacy algorithms entirely. If an older client tries to connect to this, they will get a swift protocol negotiation failure.
KexAlgorithms mlkem768x25519-sha256Securing NGINX
NGINX relies entirely on the underlying cryptographic library installed on the OS. By targeting OpenSSL 3.5+, we get native support for ML-KEM (for key exchange) and ML-DSA (for digital signatures) without needing external plugins like `oqs-provider`.
To make NGINX completely quantum-safe, we have to look at three things: the **key exchange** (to stop "harvest now, decrypt later"), the **symmetric ciphers** (to protect against Grover's algorithm cutting key strength in half), and the **authentication signatures** (to stop a quantum computer from spoofing your server). While migrating to ML-KEM is an immediate priority to stop data harvesting, migrating to ML-DSA signatures is a future-proofing measure to prevent active, real-time spoofing once quantum computers actually come online.
Because TLS 1.3 handles these beautifully, we will enforce TLS 1.3 and use the `ssl_conf_command` directive to pass direct instructions to OpenSSL 3.5.
Option 1: Quantum-Safe but Backward Compatible (Hybrid)
This is the safest route for a public-facing web server. You mitigate the immediate harvesting threat for modern browsers (like recent versions of Chrome and Firefox that already support hybrid quantum key exchanges) without breaking the site for someone on an older device.
In your NGINX server block:
ssl_protocols TLSv1.3;# 1. Key Exchange: Prefer native X25519/ML-KEM hybrid, fallback to standard curvesssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;# 2. Symmetric Ciphers: Enforce 256-bit encryption first to neutralize Grover's algorithmssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256;# 3. Signature Algorithms: Allow PQC ML-DSA signatures alongside legacy RSA/ECDSAssl_conf_command SignatureAlgorithms p384_mldsa65:mldsa65:ecdsa_secp384r1_sha384:rsa_pss_rsae_sha256;Option 2: Strict Quantum-Safe Only
If you want to lock down a bunker and ensure zero legacy tech touches your web server, you strip away the fallbacks. This means you only accept 256-bit symmetric ciphers, pure hybrid PQC key exchanges, and you absolutely must have an ML-DSA certificate installed on the server because NGINX will flat-out reject traditional RSA or ECDSA signatures.
ssl_protocols TLSv1.3;# 1. Key Exchange: Strictly hybrid ML-KEMssl_ecdh_curve X25519MLKEM768;# 2. Symmetric Ciphers: Strictly AES-256ssl_conf_command Ciphersuites TLS_AES_256_GCM_SHA384;# 3. Signature Algorithms: Strictly ML-DSA for server authenticationssl_conf_command SignatureAlgorithms mldsa65:p384_mldsa65;A Practical Warning
Granted, if you try to spin up that strict NGINX configuration right now on a standard, stock Linux distribution, it’s probably going to crash on startup unless it is an extremely new version (as of this date).
Why? Two reasons. First, stable operating systems like Ubuntu 24.04 ship with older, stable versions of OpenSSL (like 3.0.x), meaning you’ll have to manually compile OpenSSL 3.5+ and build NGINX against it to get these native strings. Second, if you tell OpenSSL to strictly demand `mldsa65` signatures, but your `ssl_certificate` directive points to a standard RSA certificate you got from Let's Encrypt, OpenSSL will refuse to complete the handshake. Public Certificate Authorities aren't widely handing out production-ready ML-DSA certs just yet. In theory you could “roll your own” but that is not without its own concerns and simply beyond the scope of what this blog post is covering.
Regardless, the hybrid approach is ready for prime time if you compile the underlying tools. It gives you the best of both worlds right now: immediate protection against adversaries scooping up your traffic today to decrypt on Q-Day, while keeping the lights on for older clients.
Enjoy the configs, and have fun breaking your test servers before you try this in production.
