8 min read

Quantum-Resistant Transition with OpenSSL 3.5

Quantum-Resistant Transition with OpenSSL 3.5

OpenSSL 3.5 introduces three post-quantum primitives - ML-DSA, SLH-DSA and ML-KEM - all standardized in FIPS-203/204/205 and believed to withstand large-scale quantum attacks. Large-scale quantum computers will eventually break RSA and ECC. OpenSSL 3.5 ships the first NIST-approved post-quantum algorithms, giving teams a concrete migration path. 

This blog shows a minimal, reproducible lab build of OpenSSL 3.5 on Red Hat Enterprise Linux 9.6, validates the new algorithms and compares their performance, giving you a starting point for pilot deployments. 

Policy Pressure Is Mounting 

Future large-scale quantum computers will be able to break the asymmetric cryptography in use today, including RSA and elliptic-curve systems. 

The National Security Agency’s Commercial National Security Algorithm Suite 2.0 (CNSA 2.0), released in September 2022, sets an aggressive timetable for migrating U.S. federal systems to quantum-resistant cryptography. In April 2025 the European Cybersecurity Certification Group (ECCG) published version 2 of The Agreed Cryptographic Mechanisms, adding recommendations on post-quantum algorithms; enabling EU legislation is expected to follow.

Organizations should treat the transition seriously even if regulation has not yet reached them; building prototypes early reduces future cut-over risk. 

Here’s a straightforward first step. 

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:

A screenshot of a computer program

AI-generated content may be incorrect.

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. 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. 

Micro-Benchmarks 

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.  

TLS 1.3 Handshake Latency 

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.  

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 

 Important note 

You are not required to switch to quantum-resistant signature algorithms immediately, if it is used for authenticity in a protocol where the signature can easily be replaced within months. In TLS, a signature proves trust at the moment of the handshake; a future quantum computer thus cannot retroactively break that one-off assertion. By contrast, the key-exchange step generates the symmetric key that protects the session traffic – this key exchange an attacker could harvest today and decrypt when a CRQC (cryptographic relevant quantum computer) is developed. 
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-current performance for key exchange, with 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 today’s traffic can be stored and decrypted later. 
  • ML-DSA is a fast, size-heavier alternative to current 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. 

PQC Blog

Cryptomathic is an industry leader in cryptographic key management and crypto-agility solutions. Download the eBook on Post Quantum Computing and Crypto Agility or contact us to discuss your needs.