Post-Quantum Cryptography Implementation Considerations in TLS

Jan Schaumann

Written by

Jan Schaumann

August 06, 2025

Jan Schaumann

Written by

Jan Schaumann

Jan Schaumann, Chief Information Security Architect at Akamai, has more than 20 years of experience building and securing high-availability services at internet scale. At Akamai, he launched our bug bounty program, works with the Architecture Group on a range of company-wide initiatives, represents InfoSec in the Open Source Working Group, and leads the internal Cryptography Group, among other initiatives. His research interests cover the overall health of the internet, as well as the safety and privacy of its users.

There’s much to consider as you implement PQC using the new TLS 1.3 hybrid key exchange on client and server applications.
There’s much to consider as you implement PQC using the new TLS 1.3 hybrid key exchange on client and server applications.

Contents

On June 30, 2025, Akamai rolled out support for post-quantum cryptography (PQC) in Ghost to Origin (G2O) connections using Transport Layer Security (TLS) version 1.3. This new feature is currently in limited availability, and early adopters can enable it to protect connections between Akamai and origin servers against the "harvest now, decrypt later" (HNDL) threat.

We are planning to enable this feature on all origin TLS connections with our upcoming general availability release on October 31, 2025. In preparation for that release, let’s take a closer look at the implementation. Our objective is to assist customers in their preparedness and enablement by sharing what considerations come into play as we embark together on this journey to a quantum-secure future.

Libraries and tools

To deploy PQC that interoperates — on the client side or the server side — you’ll need a TLS library or framework that supports the latest TLS 1.3 hybrid key exchange using a post-quantum traditional hybrid scheme.

Since common cryptographic libraries like OpenSSL have only recently received support for the newly standardized post-quantum algorithms, Akamai not only developed our own PQC provider, but at the same time invested in platform-wide upgrades, yielding an overall more crypto-agile state.

The resulting flexibility is essential for adopting PQC and defending against the HNDL active threat. Likewise, you will need to assess your infrastructure to identify necessary library updates.

In this blog post we’ll share some common implementation challenges for TLS 1.3 hybrid key exchange adoption, using the latest OpenSSL and BoringSSL libraries as examples, to help you prepare for a quantum-secure future.

TLS 1.3 hybrid key exchange

In our previous blog post in this series, we shared:

But what does a hybrid key exchange actually look like, and how does it impact client and server behavior? As you adopt PQC, it’s important to understand the difference in its behavior, both compared with the classic handshake as well as between client and server.

Sample environment

To observe the TLS packets on the wire, we need an HTTP server that supports PQC. We’ve already published a simple guide explaining how to set up PQC using nginx on an Ubuntu Linode, which you can reference for exactly that purpose.

Following that guide to configure an example site (https://pqc.example.com), we can then explore the TLS handshake using tcpdump and the openssl s_client command:

  $ sudo tcpdump -w pqc.pcap host pqc.example.com >/dev/null 2>&1
  $ </dev/null openssl s_client -tls1_2 -connect pqc.example.com:443
  [...]
  $ </dev/null openssl s_client -connect pqc.example.com:443
  [...]

Since we are focused only on the TLS handshake here, we don’t need to make an actual HTTP request. Having made two successive connections — the first using TLS 1.2 and the second using the default TLS 1.3 — we can now inspect the captured packets for differences in the key exchange.

Key exchange differences in TLS 1.2 vs. TLS 1.3

In a traditional TLS 1.2 handshake, as in the first openssl invocation, the client indicates all supported cipher suites in the TLS ClientHello  — including the key exchange algorithms to be used for each cipher suite.

For example, the cipher suite ECDHE-ECDSA-AES256-GCM-SHA384 specifies the use of Elliptic Curve Diffie–Hellman (ECDH) for the key exchange. On the other hand, for example, DHE-RSA-AES256-GCM-SHA384 specifies the use of the original (Finite Field) Diffie–Hellman. The supported_groups extension advertises the appropriate key groups, but only sends the suitable public key in the subsequent Client Key Exchange message (Figure 1).

The supported_groups extension advertises the appropriate key groups, but only sends the suitable public key in the subsequent Client Key Exchange message (Figure 1). Fig. 1: This Wireshark screenshot shows the details of the Client Key Exchange packets of a TLS 1.2 handshake, highlighting the public key provided by the client

By contrast, in a TLS 1.3 handshake, the key exchange algorithm selection is separated from the authentication algorithms in the cipher suites. The client provides the public key right in the ClientHello as part of the key_hare extension (Figure 2).

The client provides the public key right in the ClientHello as part of the key_hare extension (Figure 2). Fig. 2: This Wireshark screenshot shows the details of a TLS 1.3 handshake, highlighting the different key groups indicated alongside the two key shares immediately supplied in the key share extension

TLS ClientHello compatibility

In the packet analysis above, we see that the client supports PQC using X25519MLKEM768 and includes both a standalone X25519 key and a hybrid key — the latter consisting of the concatenation of a separate X25519 public key and the ML-KEM public key.  (You can read a more detailed discussion of the hybrid key exchange on my personal blog.)

This combination of keys leads to an increase of bytes in the ClientHello compared with legacy algorithms (Table).

Algorithm

Public key (bytes)

X25519

32

RSA-2048

256

ML-KEM768

1,184

X25519MLKEM768

1,216

Table: Comparison of public key sizes

This increase in size brings up its own set of challenges. Under certain circumstances, it can cause faulty server implementations to reject the ClientHello. Additionally, generating and sending this larger hybrid key in every ClientHello wastes CPU use and bandwidth if the remote server does not even support PQC.

One option to avoid these inefficiencies is for the client to advertise both key groups, but only include one key share in the ClientHello. For example, imagine that the client advertises both X25519 and X25519MLKEM768, but only offers the X25519 key share. If the server doesn’t speak PQC, it will simply use the offered X25519 key to establish the connection. Otherwise, it would have to initiate a HelloRetryRequest to select X25519MLKEM768, incurring an additional round trip.

Alternatively, if the client offered only the hybrid key share, couldn’t a server without support for PQC extract the X25519 component and use that for the classical key exchange? While that may seem like a plausible solution, it would violate cryptographic principles of only ever using a given primitive in the intended context. A server that supports only classic key exchange talking to a client that offers only the hybrid key share would therefore have to trigger a HelloRetryRequest to request the standalone X25519 key from the client.

You can compare both options side-by-side in Figure 3 and Figure 4.

Client-server communication requiring a HelloRetryRequest to use X25519MLKEM768 Fig. 3: Client-server communication requiring a HelloRetryRequest to use X25519MLKEM768 after the client only included the X25519 key share
Fig. 4: Client-server communication requiring a HelloRetryRequest to use X25519 Fig. 4: Client-server communication requiring a HelloRetryRequest to use X25519 after the client only included the X25519MLKEM768 key share

To mitigate these problems, clients must determine the right approach as a trade-off between increased ClientHello size and incurring additional round trips via a HelloRetryRequest. Common clients, such as browsers, favor shorter connection times at the cost of a larger ClientHello, but this may not be the best approach for your application.

For example, if you use long-lived persistent connections but expect few servers to actually support PQC, you may want to only offer the single classic key, but support the hybrid key group if the server initiates a HelloRetryRequest. This will be Akamai’s long-term approach for G2O connections for customers who don’t explicitly signal PQC support.

Alternatively, if you know the server you’re talking to supports PQC, you can immediately and only offer X25519MLKEM768 in the ClientHello. This is Akamai’s approach during our limited availability phase, and once PQC support becomes generally available, it will be our approach for customers who explicitly signal PQC support.

While you can simulate these scenarios easily enough using the openssl s_client command, you’ll want to carefully read your TLS library’s manual page to understand how group preference is specified. For example, OpenSSL’s SSL_CTX_set1_curves(3) offers a somewhat unintuitive definition, whereby specifying X25519:X25519MLKEM768 leads to the client only including the X25519 key (but advertising both), while X25519:*X25519MLKEM768 (note the asterisk) only includes the PQC hybrid key. To include both, you’d have to use *X25519:*X25519MLKEM768.

In BoringSSL, on the other hand, all keys specified in the -curves option are included in the ClientHello. That is, the command-line client does not support advertising multiple key groups but only including a single key share.

To observe the difference, run the following commands:

  $ sudo tcpdump -w pqc.pcap host pqc.example.com >/dev/null 2>&1
  $ </dev/null openssl s_client -groups "X25519:X25519MLKEM768"   \
        -connect pqc.example.com:443
  $ </dev/null openssl s_client -groups "X25519:*X25519MLKEM768"  \
        -connect pqc.example.com:443
  $ </dev/null openssl s_client -groups "*X25519:*X25519MLKEM768" \
        -connect pqc.example.com:443
  $ </dev/null bssl client -curves "X25519:X25519MLKEM768"        \
        -connect pqc.example.com:443

In the resulting packet capture, you should find a HelloRetryRequest triggered during the first connection, while subsequent connections include the X25519MLKEM768 immediately in the ClientHello. The last two connections will include both key groups.

For a server, the behavior is different once again. Since a server responds to the client and does not need to send any key shares opportunistically, specifying key groups may instead signal its list of preference order to avoid round trips.

As this suggests, a client or server that’s uniquely configured for your specific environment may have different priorities and compatibility models than general purpose clients (such as browsers) or servers (such as a CDN edge server).

Verifying the key exchange

With so many configuration options and software/library combinations, you’ll want to be able to easily identify whether a given connection uses the hybrid key exchange. 

Validating a client

To validate that a client connecting to your server uses the X25519MLKEM768 hybrid key exchange, your server may be able to extract, log, and reflect the key exchange algorithm used. This varies from server to server and further depends on the specific TLS library.

For example, in nginx, you can expose the $ssl_curve parameter to a FastCGI script. For an OpenSSL- or BoringSSL-based server, you might use the SSL_get_negotiated_group(3) function. In some languages, such as Python or Go, however, this information is not always readily available.

Validating a server

The easiest way to verify whether a given server supports PQC is to attempt to make a connection using only X25519MLKEM768. This requires a client that supports specifying the key exchange mechanism — for example, via the openssl s_client commands shown above.

In the verbose output, you should see the Negotiated TLS 1.3 Group:

  $ printf "GET / HTTP/1.1\r\nHost: pqc.example.com\r\nConnection: close\r\n\r\n" |
        openssl s_client -ign_eof -curves X25519MLKEM768 \
                -connect pqc.example.com:443
[...]
Peer signing digest: SHA256
Peer signature type: rsa_pss_rsae_sha256
Negotiated TLS1.3 group: X25519MLKEM768
[...]
New, TLSv1.3, Cipher is TLS_AES_128_GCM_SHA256
Protocol: TLSv1.3
[...]

Similarly, the ubiquitous curl command lets you specify which key exchange mechanisms to use via the --curves option, although details of the behavior vary depending on which TLS library curl was built against.

Of course, the easiest way to verify your PQC connectivity may just be to use a browser. As of August 2025, both Firefox and Chrome support, enable, and offer X25519MLKEM768 by default. While Safari does not yet support PQC, Apple recently announced that macOS Tahoe 26 and iOS 26 (expected to be released in fall 2025) will do so.

To see the key exchange group, view the details of your TLS connection via Developer Tools → Privacy and Security in Chrome (Figure 5), or via Web Developer Tools → Network → Security (Figure 6) in Firefox.

Chrome Developer Tools Fig. 5: Chrome Developer Tools showing the use of X25519MLKEM768
Firefox Web Developer Tools showing the use of X25519MLKEM768 Fig. 6: Firefox Web Developer Tools showing the use of X25519MLKEM768 by listing the keys in the order in which the hybrid key is constructed

Moving toward a quantum-secure future

Clearly, there’s much to consider as you implement PQC using the new TLS 1.3 hybrid key exchange on client and server applications.

Although you may be able to offload some of these challenges to third-party providers, it’s still important to be able to verify and test the new PQC capabilities in your respective environment. The examples we’ve shared in this post should help protect your and your users’ data from current and emerging quantum threats. Akamai is here to support you in onboarding and enabling G2O PQC and help you embark on the journey to a quantum-secure future.

Akamai’s phased approach: Our next steps

As we’ve shared previously, Akamai’s approach to securing end-to-end delivery transport includes three phases:

  • Phase one: Akamai-to-origin (Akamai-to-website)
  • Phase two: Client-to-Akamai (browser-to-Akamai)
  • Phase three: Akamai-to-Akamai

Phase one: Akamai-to-origin

As of June 30, 2025, Akamai supports PQC to origin servers using HTTP/1 and HTTP/2 with the X25519MLKEM768 hybrid key share. Customers can now opt in through their account teams for Enhanced TLS hostnames. (Support for PQC in HTTP/3-to-customer origins will be added later during the limited availability phase.)

This feature is available to all Akamai Ion and delivery customers (on Enhanced TLS) at no additional cost and will enter general availability on October 31, 2025.

We encourage all customers to enable PQC to their origins.

Phase two: Client-to-Akamai

We’re on track to launch PQC support for client browser-to-Akamai service on September 1, 2025. This limited availability opt-in feature will give early adopters a chance to secure their users’ connection to Akamai’s edge with the broadly supported X25519MLKEM768 hybrid key share.

The feature will be available to all Akamai Ion and Akamai Dynamic Site Accelerator customers (on Enhanced TLS) at no additional cost.

Phase three: Akamai-to-Akamai

We expect to complete the PQC update for mid-tier connections across all of Akamai’s networks between Q4 2025 and Q1 2026. This will be entirely transparent to all customers. All Akamai-to-Akamai connections will be quantum-safe, regardless of the client-to-Akamai or Akamai-to-origin connection settings.

Akamai is a global company operating in various markets with customers from around the world. The quantum computing revolution and its implied threats to your data do not respect borders and the solutions and defenses we develop in the larger internet community have to protect users everywhere.

In our next post, we’ll look at how governments define compliance requirements in their respective markets or jurisdictions, sharing guidance for the compliant migration from classical cryptography to PQC. Until next time!

For more information

For additional information or questions, please contact your account representative.



Jan Schaumann

Written by

Jan Schaumann

August 06, 2025

Jan Schaumann

Written by

Jan Schaumann

Jan Schaumann, Chief Information Security Architect at Akamai, has more than 20 years of experience building and securing high-availability services at internet scale. At Akamai, he launched our bug bounty program, works with the Architecture Group on a range of company-wide initiatives, represents InfoSec in the Open Source Working Group, and leads the internal Cryptography Group, among other initiatives. His research interests cover the overall health of the internet, as well as the safety and privacy of its users.

Related Blog Posts

Security

Taking Steps to Prepare for Quantum Advantage

August 12, 2024
Read how Akamai is preparing for the implementation of post-quantum cryptography and helping our customers be quantum-ready.
by Rich Salz and Jan Schaumann
Read More
Trends

Building a Quantum-Safe Internet: The IETF's Plan for TLS

June 18, 2025
Learn about the latest initiatives in post-quantum cryptography, including the IETF’s plan for securing TLS.
by Rich Salz
Read More
Security

Akamai and the Adoption of Post-Quantum Cryptography

April 27, 2023
Akamai is tracking the ongoing developments in quantum computing with great interest as we actively prepare for the wide adoption of post-quantum cryptography.
by David Rivera and Jan Schaumann
Read More