10 min read
Quantum-Resistant Transition with OpenSSL 3.5
Hans Martin Lauridsen : modified on 12. January 2026
- Home >
- Quantum-Resistant Transition with OpenSSL 3.5
OpenSSL 3.5 brings the first NIST-standardized post-quantum algorithms into the mainstream OpenSSL toolkit: ML-KEM (key exchange), ML-DSA (lattice signatures), and SLH-DSA (hash-based signatures), believed to withstand large-scale quantum attacks. Large-scale quantum computers will eventually break RSA and ECC. Teams are starting pilots now, before mandates force rushed cutovers.
This post gives you a minimal, reproducible lab build of OpenSSL 3.5 on Red Hat Enterprise Linux 9.6, then validates the new algorithms and compares their performance. Use it as a practical starting point for PQC experimentation and migration planning.
Key Takeaways:
ML-KEM key exchange is fast, but ciphertexts are much larger than X25519/ECDH.
- Hybrid key exchanges (e.g., X25519+ML-KEM-768) add quantum resistance with modest extra overhead.
- “Harvest now, decrypt later” risk makes PQ key exchange the first priority for most TLS deployments.
- ML-DSA is relatively fast but increases public key/signature sizes.
- SLH-DSA can be significantly slower and produces very large signatures—use selectively (e.g., long-lived artifacts).
Why Is The Policy Pressure Mounting?
Policy and assurance frameworks are converging on “quantum-readiness” expectations:
- The National Security Agency’s Commercial National Security Algorithm Suite 2.0 (CNSA 2.0) guidance sets an aggressive direction for U.S. national security systems to migrate to quantum-resistant algorithms.
- In the EU, the European Cybersecurity Certification Group (ECCG) “Agreed Cryptographic Mechanisms” v2.0 adds post-quantum recommendations, signaling what will become normal for certification and compliance.
Even if you’re not regulated today, building prototypes early reduces future cutover risk: you can inventory where crypto lives, test interoperability, and pressure-test infrastructure for bigger handshakes and payloads.
We will:
1) Build OpenSSL 3.5 from source on RHEL 9.6 (without replacing the system OpenSSL).
2) Confirm which KEM and signature algorithms are available.
3) Run micro-benchmarks for KEM operations and record ciphertext sizes.
4) Measure TLS 1.3 handshake latency for classical, PQ-only, and hybrid KEM groups.
Part 1 - Building OpenSSL 3.5 on RHEL 9.6
OpenSSL v3.5 is only a few months old and isn’t yet in most package repositories, so you’ll need to build it from source. The example below was tested on a Dell XPS 15 running Windows 11.
Not to worry, here is a step-by-step guide on how to do it, for this guide our target platform will be RedHat 9.6. Consider following the guide in a container by creating a dockerfile and using the latest UBI 9 image by adding
FROM redhat/ubi9:latest
at the beginning.
Build and Install
Start by making sure all your packages are up to date
# dnf update && dnf upgrade
There are several tools which are necessary to be able to build and install OpenSSL so make sure you got those
# dnf -y install perl-core zlib-devel kernel-headers make gcc wget
Once you got the prerequisites in order you can download version 3.5 of OpenSSL from the original website using wget and extract the files
# wget https://www.openssl.org/source/openssl-3.5.0.tar.gz && tar -xvzf openssl-3.5.0.tar.gz
Navigate to the folder you just extracted and run the following configuration, it will make sure that OpenSSL is installed to /usr/local to avoid any conflict with current installations of OpenSSL
# ./Configure --prefix=/usr/local/openssl --openssldir=/usr/local/openssl -Wl,-rpath=/usr/local/openssl/lib64 shared zlib
Build and install with make
# make && make install
have patience, this can take a while. Once completed you find it here /usr/local/openssl/bin/openssl. To add it to your PATH
# export PATH="/usr/local/openssl/bin:$PATH"
and finally, to verify that everything was successful we can check the version
# openssl -version
OpenSSL 3.5.0 8 Apr 2025 (Library: OpenSSL 3.5.0 8 Apr 2025)
Here is the completed version of my dockerfile:

Performance
Once you have verified the installation was successful, let's see what is available in the release by using the list command,
# openssl list -help
will display a summary of lists that we can request.
Part 2 - Validate what OpenSSL 3.5 exposes (KEMs and hybrids)
This version of OpenSSL has the -kem-algorithms flag, which will give us a list of available KEMs (Key Encapsulation Mechanism).
# openssl list -kem-algorithms
{ 1.2.840.113549.1.1.1, 2.5.8.1.1, RSA, rsaEncryption } @ default
{ 1.2.840.10045.2.1, EC, id-ecPublicKey } @ default
{ 1.3.101.110, X25519 } @ default
{ 1.3.101.111, X448 } @ default
{ 2.16.840.1.101.3.4.4.1, id-alg-ml-kem-512, ML-KEM-512, MLKEM512 } @ default
{ 2.16.840.1.101.3.4.4.2, id-alg-ml-kem-768, ML-KEM-768, MLKEM768 } @ default
{ 2.16.840.1.101.3.4.4.3, id-alg-ml-kem-1024, ML-KEM-1024, MLKEM1024 } @ default
X25519MLKEM768 @ default
X448MLKEM1024 @ default
SecP256r1MLKEM768 @ default
SecP384r1MLKEM1024 @ default
Notice how this lists several different ML-KEM versions. MLKEM512, MLKEM768 and MLKEM1024 represent ML-KEM with the parameter-sets 512, 768 and 1024 respectively which each provide a different level of security. You will also notice that there are some combinations, those being X25519MLKEM768, X448MLKEM1024, SecP256rMLKEM789 and SecP384r1MLKEM1024, these are hybrids and represents and algorithm where both algorithms provide input to a shared secret key – I will not get into the details on how exactly that is done here as these are currently in a draft state and not in scope for this short post.
Part 3 - Micro-benchmarks (KEM speed)
To see how they perform we can use the build in speed command
# openssl speed -kem-algorithms
I have summarized the output from my test run in the table below.
|
|
keygen |
encaps |
decaps |
SUM |
|
P-256 |
0,02 |
0,09 |
0,08 |
0,19 |
|
P-384 |
0,73 |
1,86 |
0,91 |
3,50 |
|
X25519 |
0,04 |
0,10 |
0,05 |
0,20 |
|
ML-KEM-512 |
0,02 |
0,02 |
0,02 |
0,06 |
|
ML-KEM-768 |
0,05 |
0,02 |
0,03 |
0,10 |
|
ML-KEM-1024 |
0,06 |
0,03 |
0,04 |
0,12 |
|
X25519-ML-KEM-768 |
0,08 |
0,09 |
0,07 |
0,24 |
|
SecP256r1-ML-KEM-768 |
0,06 |
0,11 |
0,10 |
0,27 |
|
SecP384r1-ML-KEM-1024 |
0,80 |
1,47 |
0,77 |
3,04 |
Table 1 average execution time in ms
These are of course the raw algorithms performance numbers (with respect to my personal laptop). While these are all fast it comes with a price in ciphertext sizes.
|
|
Ciphertex |
|
P-256 |
65 |
|
P-384 |
97 |
|
X25519 |
32 |
|
ML-KEM-512 |
768 |
|
ML-KEM-768 |
1088 |
|
ML-KEM-1024 |
1568 |
|
X25519-ML-KEM-768 |
1120 |
|
SecP256r1-ML-KEM-768 |
1185 |
|
SecP384r1-ML-KEM-1024 |
1665 |
Table 2 sizes in bytes
Take note that the overhead of a hybrid approach is small thus adds additional security – since you would have to break both schemes to decipher the key - at a low cost.
Part 4 - TLS 1.3 handshake latency (local test)
To put it to the test, let's have a look at the performance when incorporated in a TLS1.3 handshake. To do so we can utilize the OpenSSL tools s_time and s_server to produce some numbers, I configured my server to use TLS1.3 and AES128-GCM-SHA256, here is an average of how long it took to establish a connection with the different key exchange algorithms locally on my machine.
|
|
Handshake |
|
P-256 |
2,09 |
|
P-384 |
6,83 |
|
X25519 |
2,13 |
|
ML-KEM-512 |
1,86 |
|
ML-KEM-768 |
2,08 |
|
ML-KEM-1024 |
2,26 |
|
X25519-ML-KEM-768 |
2,36 |
|
SecP256r1-ML-KEM-768 |
2,27 |
|
SecP384r1-ML-KEM-1024 |
5,78 |
Table 3 average handshake in ms
Showing that the increase in ciphertext sizes has no significant impact on the performance in our small local test. Keep in mind that this is all running locally on my machine thus real-world examples where data needs to travel further and get through load balancers etc. will affect the numbers. Lastly, I will note that, due to the increase in the ciphertext sizes, it can be hard to fit the ClientHello into a single network package, and while this should be fine according to the standards it can cause issues when establishing connections, as some implementations wrongly does not permit splitting of the HelloClient request over multiple network packages.
Part 5 - Post-quantum signatures (ML-DSA and SLH-DSA)
To get the available signature algorithms we can use -signature-algorithms
# openssl list -signature-algorithms
[...]
{ 2.16.840.1.101.3.4.3.17, id-ml-dsa-44, ML-DSA-44, MLDSA44 } @ default
{ 2.16.840.1.101.3.4.3.18, id-ml-dsa-65, ML-DSA-65, MLDSA65 } @ default
{ 2.16.840.1.101.3.4.3.19, id-ml-dsa-87, ML-DSA-87, MLDSA87 } @ default
[...]
{ 2.16.840.1.101.3.4.3.20, id-slh-dsa-sha2-128s, SLH-DSA-SHA2-128s } @ default
{ 2.16.840.1.101.3.4.3.21, id-slh-dsa-sha2-128f, SLH-DSA-SHA2-128f } @ default
{ 2.16.840.1.101.3.4.3.22, id-slh-dsa-sha2-192s, SLH-DSA-SHA2-192s } @ default
{ 2.16.840.1.101.3.4.3.23, id-slh-dsa-sha2-192f, SLH-DSA-SHA2-192f } @ default
{ 2.16.840.1.101.3.4.3.24, id-slh-dsa-sha2-256s, SLH-DSA-SHA2-256s } @ default
{ 2.16.840.1.101.3.4.3.25, id-slh-dsa-sha2-256f, SLH-DSA-SHA2-256f } @ default
{ 2.16.840.1.101.3.4.3.26, id-slh-dsa-shake-128s, SLH-DSA-SHAKE-128s } @ default
{ 2.16.840.1.101.3.4.3.27, id-slh-dsa-shake-128f, SLH-DSA-SHAKE-128f } @ default
{ 2.16.840.1.101.3.4.3.28, id-slh-dsa-shake-192s, SLH-DSA-SHAKE-192s } @ default
{ 2.16.840.1.101.3.4.3.29, id-slh-dsa-shake-192f, SLH-DSA-SHAKE-192f } @ default
{ 2.16.840.1.101.3.4.3.30, id-slh-dsa-shake-256s, SLH-DSA-SHAKE-256s } @ default
{ 2.16.840.1.101.3.4.3.31, id-slh-dsa-shake-256f, SLH-DSA-SHAKE-256f } @ default
This returns a long list of available signature algorithms; the list is too long to reproduce here, so I’ve included only the new additions. ML-DSA-44, ML-DSA-65 and ML-DSA-87 represent ML-DSA with parameter sets 44, 65 and 87 respectively, offering increasing levels of security. For SLH-DSA, the variants follow the naming convention SLH-DSA-XXX-YYYZ.
Because SLH-DSA is a hash-based signature algorithm, the choice of hash function - SHA-2 or SHAKE, both supported by FIPS 205 - is embedded in the name. The next identifier, 128, 192 or 256, maps to NIST security levels 1, 3 or 5 (with 5 the highest), and a final letter indicates whether the profile is f for “fast” or s for “small,” reflecting the usual speed-versus-size trade-off.
OpenSSL 3.5.0.8 does not yet support the built-in benchmark command for these algorithms; to obtain performance numbers you need to integrate with the library directly. I did so to produce the figures below, measured on my personal laptop.
|
|
gen |
sign |
verify |
|
P-256 (with SHA256) |
0,02 |
0,03 |
0,09 |
|
P-384 (with SHA256) |
0,89 |
0,77 |
0,73 |
|
Ed25519 |
0,06 |
0,05 |
0,14 |
|
ML-DSA-44 |
0,14 |
0,73 |
0,14 |
|
ML-DSA-65 |
0,24 |
1,13 |
0,20 |
|
ML-DSA-87 |
0,32 |
1,30 |
0,53 |
|
SLH-DSA-SHA2-128s |
54,07 |
385,71 |
0,34 |
|
SLH-DSA-SHA2-128f |
0,88 |
19,13 |
1,01 |
|
SLH-DSA-SHA2-192s |
79,37 |
813,77 |
0,59 |
|
SLH-DSA-SHA2-192f |
1,12 |
34,73 |
1,61 |
|
SLH-DSA-SHA2-256s |
49,78 |
899,74 |
0,94 |
|
SLH-DSA-SHA2-256f |
3,02 |
66,19 |
1,90 |
|
SLH-DSA-SHAKE-128s |
138,97 |
1254,44 |
1,08 |
|
SLH-DSA-SHAKE-128f |
2,66 |
50,90 |
3,11 |
|
SLH-DSA-SHAKE-192s |
226,19 |
2186,59 |
1,41 |
|
SLH-DSA-SHAKE-192f |
3,16 |
85,23 |
4,72 |
|
SLH-DSA-SHAKE-256s |
147,44 |
1838,56 |
2,37 |
|
SLH-DSA-SHAKE-256f |
10,05 |
171,34 |
4,84 |
Table 4 average execution time in ms
On ML-DSA the performance impact is negligible compared to the classical algorithms, but with SLH-DSA even the “fast” variants introduce noticeable overhead. There is a catch; both key and signature sizes grow substantially, a factor that must be considered in any migration plan to quantum-resistant algorithms.
|
|
Public Key |
Signature |
|
P-256 |
64 |
64 |
|
Ed25519 |
32 |
64 |
|
ML-DSA-44 |
2420 |
1312 |
|
ML-DSA-65 |
3309 |
1952 |
|
ML-DSA-87 |
4627 |
2592 |
|
SLH-DSA-128s |
32 |
7856 |
|
SLH-DSA-128f |
32 |
17088 |
|
SLH-DSA-192s |
48 |
16224 |
|
SLH-DSA-192f |
48 |
35664 |
|
SLH-DSA-256s |
64 |
29792 |
|
SLH-DSA-256f |
64 |
49856 |
A practical prioritization rule (often missed)
You do not always need to switch TLS certificates to quantum-resistant signatures immediately.
- TLS signatures prove authenticity at handshake time; an attacker with a future quantum computer cannot retroactively “forge” a handshake that already happened.
- By contrast, key exchange is exposed to “harvest now, decrypt later”: an attacker can record traffic today and decrypt it later when a CRQC (cryptographic relevant quantum computer) is developed.
Where PQ signatures matter sooner
In other domains - firmware signing, code signing, e-passports - signatures cannot be refreshed easily, and product lifetimes may outlast the advent of a CRQC. In those cases, you should migrate to a quantum-resistant signature scheme as soon as practical (see Mosca’s inequality).
Final thoughts
Building OpenSSL 3.5 from source already gives you quantum-safe key-exchange and signature options. That removes many practical blockers and lets security teams run pilot deployments at low cost. I say pilots, not because the algorithms lack maturity, but because many protocols (including TLS) are still in draft; most browsers support these drafts today, so formal standardization is only a matter of time. TLS is just one use-case - others will require the same careful planning.
With modest effort you can benchmark the real-world cost of larger keys and signatures, pressure-test your infrastructure, protect critical links, and de-risk tomorrow’s mandatory cut-over.
Recommendations
- Get comfortable with the standardized algorithms - ML-DSA, SLH-DSA and ML-KEM - to start with. OpenSSL is an excellent sandbox.
- Create a Cryptographic Bill of Materials (CBOM): a detailed inventory of every cryptographic component used within your applications and systems.
- Run a pilot. TLS handshakes are a low-hanging fruit: migrate to a hybrid key-exchange such as X25519-ML-KEM-768. Tip: compile NGINX against OpenSSL 3.5 and use it as a reverse proxy.
- Identify hard-coded algorithms and replace them with configuration-driven choices. Greater crypto-agility removes pain points and lowers long-term risk.
Summary
- ML-KEM offers near-classical performance for key exchange, with much larger payloads.
- Hybrid key exchanges that include ML-KEM add security and confidence for early adopters with minimal overhead.
- Migrating key exchange to quantum-resistant methods should be prioritized, because of harvest-now-decrypt-later.
- ML-DSA is relatively fast but size-heavier than today’s common signature schemes.
- SLH-DSA is slower and larger; you can trade speed for size via the f and s variants.
- TLS certificates need not move to quantum-resistant mechanisms until vendor support stabilizes.
- Other signature use-cases (firmware, long-life documents) may need migration sooner - consult your security experts.
About Cryptomathic
Cryptomathic provides cryptographic key management and crypto-agility solutions. For deeper planning guidance, download our Post Quantum Computing and Crypto Agility or contact us to discuss your needs.
FAQs
What does “quantum-ready cryptography” mean in this post?
It means you can start testing NIST-standardized post-quantum algorithms today—ML-KEM for key exchange and ML-DSA / SLH-DSA for signatures and measure their performance and size impact in your own environment before mandates force rushed migrations.
What’s new in OpenSSL 3.5 for post-quantum cryptography?
OpenSSL 3.5 introduces built-in support for NIST-standardized post-quantum primitives: ML-KEM (Key Encapsulation Mechanism) for key exchange, ML-DSA (lattice-based digital signatures), and SLH-DSA (hash-based digital signatures).
Which post-quantum algorithm should I pilot first?
For most teams, key exchange is the best starting point - specifically ML-KEM, ideally in a hybrid construction such as X25519-ML-KEM-768 - because it directly mitigates “harvest now, decrypt later” risk.
Why prioritize key exchange over post-quantum signatures in TLS?
In TLS, signatures establish authenticity at handshake time and are not typically vulnerable to future decryption, whereas key exchange protects session secrets that attackers can record today and potentially decrypt later using a quantum computer.
What is a “hybrid” key exchange, and why use it?
A hybrid key exchange derives the session secret from both a classical algorithm (such as X25519/ECDH) and a post-quantum algorithm (such as ML-KEM), ensuring the connection remains secure unless both schemes are broken.

