Check post-quantum TLS with OpenSSL
Use this walkthrough to test one HTTPS endpoint from your machine. You will establish a fresh TLS 1.3 connection, validate the server certificate, and look for the selected key exchange group. It also gives you a classical comparison when the hybrid attempt fails.
Before you start
The commands use a POSIX shell on Linux or macOS and an approved OpenSSL 3.5-series or newer build that exposes X25519MLKEM768. The versioned reference is OpenSSL 3.5; install a currently patched, supported release through your operating system or organization's package process. On Windows, use the PowerShell walkthrough.
If the tool is missing, obtain it through that approved channel, or consult OpenSSL's source releases and verification instructions. An isolated diagnostic installation is sufficient. Replacing the machine's system TLS library can break unrelated applications.
Validation scope: these commands are reviewed against vendor documentation. The example output is illustrative; this page does not claim execution on every operating system or vendor build.
1. Identify the exact tool
command -v openssl
openssl version -a
openssl list -providers
openssl list -tls-groups -tls1_3Record the executable path, library version, and provider list. -tls-groups lists locally available groups; it does not contact the server. Continue only if the list includes X25519MLKEM768. An unknown option or absent group means this diagnostic tool cannot perform this particular check. See OpenSSL's algorithm listing reference.
2. Require a hybrid handshake
# Replace with the hostname you want to check, without https:// or a path.
target='example.com'
openssl s_client -connect "$target:443" -servername "$target" \
-verify_hostname "$target" -verify_return_error \
-tls1_3 -groups X25519MLKEM768 -brief -no_ign_eof </dev/nullThis makes an outgoing TLS connection and does not change the server. -servername selects the hostname's virtual host; -verify_hostname checks its certificate identity; -verify_return_error stops on trust errors. Restricting the offered group makes this a capability check, not a measurement of your browser's normal preference. These options are documented in s_client.
The command can wait on an unreachable peer. Stop it with Ctrl+C if needed, or use the reference Python check for bounded timeouts and structured results. A timeout is inconclusive.
3. Read the evidence
Illustrative excerpt: exact labels vary by OpenSSL build. Some builds print the group on a Server Temp Key line.
Protocol version: TLSv1.3
Ciphersuite: TLS_AES_256_GCM_SHA384
Verification: OK
Negotiated TLS1.3 group: X25519MLKEM768- TLSv1.3 + successful verification + X25519MLKEM768: hybrid key establishment was observed on this connection.
- TLS_AES_256_GCM_SHA384 alone: a symmetric cipher suite, not the selected key exchange group.
- No selected group, trust failure, or aborted handshake: do not record a positive result just because ML-KEM appears somewhere in the output.
Save the target, time, tool version, group, and verification result in your readiness worksheet. A CDN-facing result covers that edge; it does not cover the origin or another application's TLS library.
4. Compare and troubleshoot
Run a separate classical TLS 1.3 connection using the same target and trust checks:
openssl s_client -connect "$target:443" -servername "$target" \
-verify_hostname "$target" -verify_return_error \
-tls1_3 -groups X25519 -brief -no_ign_eof </dev/null| Observation | Next action |
|---|---|
| Hybrid succeeds | Record this endpoint's capability, then test the real client and any origin/internal hop. |
| Classical succeeds, hybrid fails | Inspect server group policy and intervening proxies. This pair does not identify which component rejected hybrid. |
| Both fail | Check DNS, port, TLS 1.3 availability, firewall, certificate chain, and whether the service requires STARTTLS or a client certificate. |
| Unknown group locally | Use a supported tool build; do not count this as a remote server result. |
| Certificate verification fails | Repair the chain or use your administrator's trusted CA bundle with -CAfile. Keep verification enabled. |
5. Change the component that owns TLS, then retest
For your own server, upgrade through the server vendor's supported packages and review its group policy: start with the nginx or Cloudflare guide. For an application, identify its actual runtime; installing this executable does not upgrade Node.js, a browser, or a bundled library.
Save the known-working package/configuration before a staged change. Repeat both commands, a normal client request, and your application health checks. If errors increase, restore the previous supported package/configuration through the same deployment process and retest it. Record the temporary classical dependency and a follow-up owner.
Documentation reviewed 25 September 2026. Review covers the cited OpenSSL 3.5 interfaces; distribution support and defaults must be checked for your installed release.