Post Quantum Encryption with NGINX on Ubuntu 24.04

Select distribution:
Traducciones al Español
Estamos traduciendo nuestros guías y tutoriales al Español. Es posible que usted esté viendo una traducción generada automáticamente. Estamos trabajando con traductores profesionales para verificar las traducciones de nuestro sitio web. Este proyecto es un trabajo en curso.
Create a Linode account to try this guide with a $ credit.
This credit will be applied to any valid services used during your first  days.

The National Institute of Standards and Technology (NIST) recently released its first finalized Post-Quantum Encryption Standards to protect against quantum computer attacks. This includes the Module-Lattice-based Key-Encapsulation Mechanism standard (ML-KEM, defined in FIPS-203). It is already being implemented in the industry using an early pre-standardization draft for use with TLS.

Deploying this algorithm for your web server currently requires some additional steps. The process may vary depending on your operating system’s version of OpenSSL. This guide shows how to deploy this algorithm with NGINX on Ubuntu 24.04, using the Open Quantum Safe (OQS) provider for OpenSSL, which is used to enable the post quantum encryption algorithm. After it is configured for the web server, several ways to verify that the server is using the algorithm are demonstrated.

Before You Begin

  1. To follow along with the steps in the guide, create a Compute Instance running Ubuntu 24.04. See the Get started and Create a compute instance product documentation for instructions. You may also choose to adapt the configuration from this guide to an existing NGINX installation.

  2. Follow the Set up and secure a Compute Instance product documentation to appropriately secure your system.

  3. To implement the algorithm in NGINX, a TLS certificate is required. When using a certificate from a public certificate authority, a domain name or subdomain must be assigned to your Linode instance. Visit your domain name registrar’s website to assign a new record to your Linode instance’s IP address. Your IP address is displayed in the cloud manager. If you use the Linode DNS Manager, visit the manage DNS records product documentation to view instructions for assigning a new A/AAAA record to your IP address.

  4. For an overview of how TLS encryption works, review the Understanding TLS Certificates and Connections guide.

Note
This guide is written for a non-root user. Commands that require elevated privileges are prefixed with sudo. If you’re not familiar with the sudo command, see the Users and Groups guide.

Install Dependencies

Once your Ubuntu 24.04 compute instance is set up and secured, install the dependencies and system packages needed to build the OQS provider.

  1. Update your package list to ensure you download the latest available versions:

    sudo apt update
  2. Install cmake, a cross-platform build system generator that helps automate the compilation and build process for software projects:

    sudo apt install -y cmake
  3. Install libssl-dev, which provides development libraries and headers for OpenSSL, needed to build software that requires cryptographic functions and secure communications:

    sudo apt install -y libssl-dev
  4. Install ninja-build, a fast and lightweight build system designed to run builds in parallel, speeding up the compilation of large projects:

    sudo apt install -y ninja-build

Check if you have already installed OpenSSL 3.x +

openssl version

If OpenSSL 3.x+ is already installed, go to the “Install the oqs-provider” step.

Update OpenSSL

  1. Update OpenSSL from Ubuntu repositories:

    sudo apt install -y openssl
  2. Verify that you now have OpenSSL >= 3.x:

    openssl version

Install oqs-provider

The oqs-provider is a library that integrates post-quantum cryptographic algorithms into OpenSSL. This section outlines the steps needed to install it and leverage this advanced cryptography.

Clone the oqs-provider Repository

  1. Use git to clone the oqs-provider repository from GitHub:

    git clone https://github.com/open-quantum-safe/oqs-provider.git
  2. Change into the oqs-provider directory:

    cd oqs-provider

Build oqs-provider

  1. Set the OpenSSL root directory and build the oqs-provider using the provided script:

    scripts/fullbuild.sh
    Note
    This process may take a few minutes depending on your system.
  2. Use cmake to install the compiled oqs-provider:

    sudo cmake --install _build
  3. Run the test suite to verify the oqs-provider build:

    scripts/runtests.sh

    The tail of the output from the tests should resemble:

    100% tests passed, 0 tests failed out of 6
    
    Total Test time (real) =  93.97 sec
    
    All oqsprovider tests passed.

Configure OpenSSL to Use the OQS Provider

Use nano to edit the OpenSSL configuration file:

sudo nano /etc/ssl/openssl.cnf

Add the following lines at the end:

File: /etc/ssl/openssl.cnf
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# PQC via OpenQuantumSafe
[provider_sect]
default = default_sect
oqsprovider = oqsprovider_sect

[default_sect]
activate = 1

[oqsprovider_sect]
activate = 1

When done, press CTRL+X, followed by Y then Enter to save the file and exit nano.

Check Provider Version Information

List the active OpenSSL providers to verify the installation:

openssl list -providers

You should see output similar to the following:

Providers:
  default
    name: OpenSSL Default Provider
    version: 3.0.13
    status: active
  oqsprovider
    name: OpenSSL OQS Provider
    version: 0.7.1-dev
    status: active

Verify the Quantum-Safe KEM Algorithms are Available

Run:

openssl list -kem-algorithms -provider oqsprovider | egrep -i "(kyber|kem)768"

Output should resemble:

  kyber768 @ oqsprovider
  p384_kyber768 @ oqsprovider
  x448_kyber768 @ oqsprovider
  x25519_kyber768 @ oqsprovider
  p256_kyber768 @ oqsprovider
  mlkem768 @ oqsprovider
  p384_mlkem768 @ oqsprovider
  x448_mlkem768 @ oqsprovider
  X25519MLKEM768 @ oqsprovider
  SecP256r1MLKEM768 @ oqsprovider

Set Up NGINX

Install NGINX

Use apt to install NGINX:

sudo apt install nginx

Set up TLS/SSL Certificates

Ensure that you include the necessary certificates (whether self-signed or from a trusted Certificate Authority) to enable proper TLS/SSL functionality. Without certificates, you won’t be able to establish a secure HTTPS connection.

  • Using Let’s Encrpyt (Recommended for Production): To use automatic certificate renewal with Let’s Encrypt, follow Use Certbot to Enable HTTPS with NGINX on Ubuntu to properly configure the Nginx server.

  • Using Self-Signed Certificate (Suitable for Testing/Development): To use a self-signed certificate, see our Enable TLS/SSL for HTTPS guide, or create certificates using the following command:

    1. First create the directory for your certificates:

      sudo mkdir /opt/certs
    2. Then generate the self-signed certificate:

      sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /opt/certs/pqc.key -out /opt/certs/pqc.crt

Configure NGINX

  1. Edit the main Nginx configuration file:

    sudo nano /etc/nginx/nginx.conf
  2. Locate the http block and add the highlighted lines to include configuration files in the /etc/nginx/nginx.conf directory:

    File: /etc/nginx/nginx.conf
    18
    19
    20
    21
    22
    
    http {
        #Include additional configuration files
        include /etc/nginx/conf.d/pqc.conf;
        ...
    }

    When done, press CTRL+X, followed by Y then Enter to save the file and exit nano.

  3. Create a server configuration file called pqc.conf in the /etc/nginx/conf.d/ directory:

    sudo nano /etc/nginx/conf.d/pqc.conf

    Paste this snippet into the file. Be sure to update the ssl_certificate and ssl_certificate_key parameters with the correct file paths for your certificate files:

    File: /etc/nginx/conf.d/pqc.conf
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name example.com www.example.com;
        root /var/www/example.com;
        index index.html index.php;
        ssl_certificate /opt/certs/pqc.crt;
        ssl_certificate_key /opt/certs/pqc.key;
        ssl_protocols TLSv1.3;
        ssl_prefer_server_ciphers on;
        ssl_ecdh_curve X25519MLKEM768:x25519_kyber768:p384_kyber768:x25519:secp384r1:x448:secp256r1:secp521r1;
        location / {
            try_files $uri $uri/ =404;
        }
    }

    When done, press CTRL+X, followed by Y then Enter to save the file and exit nano.

  4. Reload the NGINX service:

    sudo systemctl reload nginx

Verify Nginx Is Using Post-Quantum Algorithms

Option 1: test with openssl s_client command

To test the TLS configuration with Kyber groups using the openssl s_client command, you can use the following options:

openssl s_client -groups x25519_kyber768 -connect localhost:443

Option 2: Capture connection using tcpdump

  1. Enable Kyber support in either Google Chrome or Mozilla Firefox:

    • Chrome:

      1. Open Chrome and navigate to chrome://flags.

      2. In the search bar, enter TLS 1.3 post-quantum key agreement.

      3. Toggle the option to Enabled for #enable-tls13-kyber or #use-ml-kem.

    • Firefox:

      1. Open Chrome and navigate to about:config.

      2. In the search bar, enter security.tls.enable_kyber.

      3. Toggle the option to True for security.tls.enable_kyber.

  2. Run tcpdump to capture the network traffic between your browser and the server. In a terminal on your workstation:

    sudo tcpdump -w pqc.pcap host <your-linode-IP-address>
  3. Visit your site using Chrome or Firefox.

  4. Use Wireshark/Tshark to analyze the captured data:

    tshark -r pqc.pcap -V | grep X25519Kyber768Draft00

    Look for the use of x25519Kyber768Draft00 as one of the key shares within the TLS handshake extension. You should see output like this:

    Extension: key_share (len=1263) X25519Kyber768Draft00, x25519
                    Type: key_share (51)
                    Length: 1263

Option 3: Display TLS Connection Details with PHP

These steps create an index.php page on your web server that displays information about your encryption algorithm:

  1. On your web server, install PHP 8.3 with FPM:

    sudo apt install -y php-fpm
  2. Edit /etc/nginx/conf.d/pqc.conf:

    1. Change the index parameter to point to the new index.php file:

      File: /etc/nginx/conf.d/example.com.conf
      1
      2
      3
      4
      
      server {
          ...
          index             index.php;
          ...
    2. Add a new location ~ \.php$ block above the existing location / block:

      File: /etc/nginx/conf.d/example.com.conf
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      
      server {
          ...
      
              location ~ \.php$ {
                  include snippets/fastcgi-php.conf;
                  fastcgi_param SSL_CURVE $ssl_curve;
                  fastcgi_pass unix:/var/run/php/php-fpm.sock;
              }
      
              location / {
                  try_files $uri $uri/ =404;
              }
      }
  3. Create a file named index.php in /var/www/example.com with this snippet:

    sudo mkdir -p /var/www/example.com
    File: /var/www/example.com/index.php
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>SSL Curve Information</title>
    </head>
    <body>
        <h1>Your SSL Curve Information</h1>
    
        <?php
            $ssl_curve = $_SERVER['SSL_CURVE'];
    
            if ($ssl_curve === '0x6399') {
                echo "<p class='secure'>You are using X25519Kyber768Draft00 which is post-quantum secure.</p>";
            } elsif ($ssl_curve === '0x4588') {
                echo "<p class='secure'>You are using X25519MLKEM768, which is post-quantum secure.</p>";
            } else {
                echo "<p class='not-secure'>You are using SSL Curve: {$ssl_curve} which is not post-quantum secure.</p>";
            }
        ?>
    
    </body>
    </html>
  4. Reload NGINX:

    sudo systemctl reload nginx
  5. Visit your website in your browser. If Kyber support is enabled in your browser, and if the TLS handshake with the web server uses the algorithm, you should see:

    You are using X25519Kyber768Draft00 which is post-quantum secure

    Otherwise, this message is displayed:

    You are using SSL Curve: X25519 which is not post-quantum secure.
Note

Remember that currently not all browsers support post-quantum algorithms. These browsers offer compatibility:

  • Enabled by default for Chrome 124+ on Desktop. For older Chrome versions or on mobile, you need to toggle TLS 1.3 post-quantum key agreement / #use-ml-kem in chrome://flags.

  • Enabled by default for Edge 124+.

  • Enabled by default for recent Opera and Brave.

  • Enabled for Firefox 124+ if you turn on security.tls.enable_kyber in about:config. Firefox 128+: turn on network.http.http3.enable_kyber for QUIC/HTTP3.

More Information

You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

This page was originally published on


Your Feedback Is Important

Let us know if this guide was helpful to you.


Join the conversation.
Read other comments or post your own below. Comments must be respectful, constructive, and relevant to the topic of the guide. Do not post external links or advertisements. Before posting, consider if your comment would be better addressed by contacting our Support team or asking on our Community Site.
The Disqus commenting system for Linode Docs requires the acceptance of Functional Cookies, which allow us to analyze site usage so we can measure and improve performance. To view and create comments for this article, please update your Cookie Preferences on this website and refresh this web page. Please note: You must have JavaScript enabled in your browser.