Post-quantum TLS: Ready or not, here I come.. 🎡

I was looking into the state of post-quantum (PQ) TLS lately. This short article summarizes how you can create PQ-ready TLS certificates today.

#tls #pqc #PKI #certificates

liboqs is a library for prototyping and experimenting with quantum-resistant cryptography. It's used by the unsupported fork of OpenSSL of the Open Quantum Safe (OQS) project. With that fork, we can easily create TSL certificates that can be used in a PQ-secure client-server TLS communication.

First you have to build the library, liboqs. On NixOS, I use these dependencies for the build:

# shell.liboqs.nix
{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
    nativeBuildInputs = with pkgs.buildPackages; [
      cmake
      pkg-config
      openssl
      ninja
      libtool
      gcc
    ];
    buildInputs = with pkgs.buildPackages; [ openssl ];
    LD_LIBRARY_PATH = pkgs.lib.makeLibraryPath [ pkgs.openssl ];
}

The build process itself is straight forward. It involves building liboqs and the OpenSSL fork:

# prepare environment
$ nix-shell shell.liboqs.nix

# clone openssl fork
$ git clone --branch OQS-OpenSSL_1_1_1-stable \
   https://github.com/open-quantum-safe/openssl.git openssl.git

# clone liboqs
$ git clone -b main https://github.com/open-quantum-safe/liboqs.git liboqs.git

$ cd liboqs.git

# build liboqs into the folder of the openssl fork (CMAKE_INSTALL_PREFIX)
$ cmake -GNinja -DCMAKE_INSTALL_PREFIX=$HOME/Downloads/pqc/openssl.git/

# openssl >= 3.0.0 (3.0.14)
$ oqs -DOQS_USE_OPENSSL=OFF ..

$ ninja
$ ninja install

# build openssl fork
$ cd ../openssl.git
$ ./Configure no-shared linux-x86_64 -lm
$ make -j

$ apps/openssl version
OpenSSL 1.1.1u  30 May 2023, Open Quantum Safe 2023-07

Luckily, the project includes short instructions on how to use the PQ-ready OpenSSL version to create web server certificates:

# create hybrid rsa/dilithium CA with the provided ssl config
$ apps/openssl req -x509 -new -newkey rsa3072_dilithium2 \
   -keyout rsa3072_dilithium2_CA.key -out rsa3072_dilithium2_CA.crt \
   -nodes -subj "/CN=oqstest CA" -days 365 -config apps/openssl.cnf

# check CA certificate
$ apps/openssl x509 -in rsa3072_dilithium2_CA.crt -noout -text

# create hybrid rsa/dilithium server cert
$ apps/openssl req -new -newkey rsa3072_dilithium2 \
   -keyout rsa3072_dilithium2_srv.key -out rsa3072_dilithium2_srv.csr \
   -nodes -subj "/CN=oqstest server" -config apps/openssl.cnf

# sign server cert with CA cert
$ apps/openssl x509 -req -in rsa3072_dilithium2_srv.csr \
   -out rsa3072_dilithium2_srv.crt -CA rsa3072_dilithium2_CA.crt \
   -CAkey rsa3072_dilithium2_CA.key -CAcreateserial -days 365

# check server cert
$ apps/openssl x509 -in rsa3072_dilithium2_srv.crt -noout -text

# run the server
$ apps/openssl s_server -cert rsa3072_dilithium2_srv.crt \
   -key rsa3072_dilithium2_srv.key -www -tls1_3
# run the client with kyber KEX
apps/openssl s_client -groups p384_kyber768 -CAfile rsa3072_dilithium2_CA.crt

What I noticed during playing with the new algorithms: The term β€œHybrid” does not mean you can choose the type of certificate for the Key exchange (<KEX>) or signature verficiation <SIG> standard. It simply means that you need both. Think of it as a fallback. If Kyber (<KEX>) or Dilithium (<SIG>) would turn out to not be that secure as everyone thought, your TLS communication (key exchange and signature verification) will still be backed by a proven industry standard algorithm (RSA or ECDSA), because you will always need to apply both algorithms to verify the signature or decrypt the traffic. Of course, this has impact on performance (e.g., time to create, encrypt/decrypt and/or verify).

Lastly, I also checked out how I can sign a message in PQ-safe way using the Cryptographic Message Syntax (CMS):

# sign file
$ apps/openssl dgst -sign rsa3072_dilithium2_srv.key -sha256 \
   -out binary.sig -binary binary

# extract pubkey
$ apps/openssl x509 -in rsa3072_dilithium2_srv.crt -noout \
   -pubkey > rsa3072_dilithium2_srv.pem

# check signature
$ apps/openssl dgst -verify rsa3072_dilithium2_srv.pem -sha256 \
   -signature binary.sig -binary binary

Of course we could go on playing with these demos, for instance, by building an application (like Nginx or curl, see oqs-demos) with support for the new algorithms. Oh, and don't forget VPNs..

There is also a website that shows you where these new algorithms typically fail: https://tldr.fail. Also, I was wondering, when I can simply request these hybrid certifcates from my known and loved HashiCorp Vault PKI πŸ€—?

It will take some time, but I'm ready (also enabled that feature toggle in my Firefox to let servers now). Let me know what you think about the topic.

(now that I wrote the blog post I can go ahead and delete that temporary folder on my Desktop)

πŸ›œ RSS | 🐘 Mastodon | πŸ’¬ IRC