Post-Quantum Encryption on a Webserver - Overview
Go 1.23rc2’s Post-Quantum Encryption
In a forthcoming version of Go, Post-Quantum Encryption will be used. It is only available by default in the tls
package. To try out the new feature, we can write a simple webserver in Go, compile it with the latest release candidate
of Go 1.23, and check what encryption is being used for TLS.
TLS and the Role of the Key Exchange Mechanism
The Key Exchange Mechanism is the exchange of a key for symmetric cryptography. AES is the symmetric block cipher whose key needs to be exchanged. It is suitable to encrypt large amounts of data, and can be used for HTTP requests and responses. To exchange the AES key, a public key cryptography system is needed. This allows the browser and webserver to communicate the key without having a shared secret at the start of the TLS 1.3 handshake. Although too computationally expensive to encrypt the whole message, public key cryptography can encrypt an AES key which then encrypts the message.
What’s New: Kyber 768
Traditionally, the public key cryptography system used for the key exchange is elliptic curve cryptography, often using the X25519 curve. Kyber 768, on the other hand, uses lattice based cryptography - specifically a variation of the ‘Learning with Error’ problem. This is a mathematical problem where quantum computers have no particular advantage for cryptanalysis, so anyone recording your TLS handshake and the subsequent HTTP traffic should not be able to decrypt the AES key in years to come.
In fact, the X25519Kyber768Draft00 cipher suite uses both elliptic curve and Post-Quantum Cryptography. The client’s elliptic curve ephemeral share value (32 bytes) and the Kyber 768 public key (1184 bytes) are concatenated together and sent to the server. The server responds similarly with the X25519 ephemeral share (32 bytes) and the Kyber ciphertext (1088 bytes).
The use of a hybrid system means an attacker would need a powerful quantum computer and there would need to be a vulnerability in Kyber for the AES key to be determined.
Uptake of PQC
Cloudflare are using X25519Kyber768Draft00 in production. In fact, their researcher Bas Westerbaan invented the hybrid scheme. (I wrote a post on compiling Caddy with Cloudflare’s fork of Go to use Post-Quantum Cryptography.) Google Chrome now supports Kyber, and it is in use on the Google Search homepage, for visitors with a compatible browser.
Elsewhere, the OpenSSL project uses a similar hybrid system (with a different algorithm) for key encapsulation after authentication has taken place.
Building a Webserver with Go 1.23rc2
Webserver Code
I have built a simple webserver in Go 1.23rc2. Some of its details won’t be of interest to the reader, but the key parts are here:
go.mod
:
|
|
The go.mod file shows the project uses Go 1.23
Incidentally, if you run this project with Go 1.22 or previous, it still works, but hybrid Post-Quantum Cryptography is not used.
Key part of the actual code:
|
|
The code uses http.ListenAndServeTLS()
to act as a webserver
Crucially, we did not specify a TLS curve that we want to use. Under the bonnet in Go 1.23’s tls
package,
X25519Kyber768Draft00 is the default ‘curve’ (although it is really a curve and a lattice). We can specify overrides,
and that will allow us to use other curves, but the x25519Kyber768Draft00
value is un-exported in Go 1.23, meaning it
can’t be specified by the user of the tls
package. It is likely to stay this way until NIST finalises a new standard,
and the Go team are comfortable committing to a public API for the Kyber integration.
Testing Our Webserver
We can test our webserver by navigating to https://localhost:8443
(or whatever port number has been configured.)
Looking at the dev tools in Chrome, we can see the relevant cipher suite:
A screenshot of Google Chrome developer tools. The cipher suite is X25519Kyber768Draft00
“The connection to this site is encrypted and authenticated using TLS 1.3, X25519Kyber768Draft00, and AES_128_GCM”
We can see that our browser and our webserver are talking to each other using X25519Kyber768Draft00 hybrid Post-Quantum Cryptography.
As noted before, this is only if you use Go 1.23rc2. In Go 1.22, plain X25519 is used.