Post Quantum Encryption with NGINX on Debian 11

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 Debian 11, using the Open Quantum Safe (OQS) provider for OpenSSL, which is used to enable the post quantum encryption algorithm.

Note
On Debian 11, the versions of OpenSSL and NGINX available from apt are not compatible with post quantum encryption, so this guide shows how to build them from source instead. On Ubuntu 24.04, post quantum encryption-compatible versions are available through apt, and this guide describes how to configure the encryption algorithm on that distribution.

Before You Begin

  1. To follow along with the steps in the guide, create a Compute Instance running Debian 11. 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 Debian 11 compute instance is set up and secured, install the dependencies and system packages needed to build OpenSSL and the OQS provider.

  1. First, update your package list to ensure you download the latest available versions:

    sudo apt update
  2. Next, install make, a build automation tool used to compile and link programs from source code. It reads instructions from a Makefile, which defines how to compile and build the software:

    sudo apt install -y make
  3. Now install gcc (GNU Compiler Collection), which compiles source code written in languages like C and C++ into executable programs. It is essential for building OpenSSL and other software from source code:

    sudo apt install -y gcc

Install OpenSSL from Source

Debian 11 comes with OpenSSL version 1.1.1w by default, but the OQS provider requires OpenSSL 3.x. Therefore, you need to build a newer version from source.

  1. First, change into your user’s home directory, if not already:

    cd ~
  2. Download the OpenSSL source code:

    wget https://github.com/openssl/openssl/releases/download/openssl-3.4.0/openssl-3.4.0.tar.gz
  3. Download the corresponding signature file:

    wget https://github.com/openssl/openssl/releases/download/openssl-3.4.0/openssl-3.4.0.tar.gz.asc

Verify the OpenSSL Code Signature

Before proceeding with the installation, verify the integrity and authenticity of the downloaded files using GnuPG (gnupg).

  1. First, install gnupg:

    sudo apt -y install gnupg
  2. Next, import the public OpenSSL signing key:

    gpg --search-keys openssl@openssl.org

    When prompted, press the 1 key followed by ENTER to choose the key from openssl@openssl.org:

    gpg: directory '/home/USERNAME/.gnupg' created
    gpg: keybox '/home/USERNAME/.gnupg/pubring.kbx' created
    gpg: data source: https://keys.openpgp.org:443
    (1)	OpenSSL <openssl@openssl.org>
        4096 bit RSA key 216094DFD0CB81EF, created: 2024-04-08
    Keys 1-1 of 1 for "openssl@openssl.org".  Enter number(s), N)ext, or Q)uit >

    Afterward, you should see output similar to the following:

    gpg: /home/USERNAME/.gnupg/trustdb.gpg: trustdb created
    gpg: key 216094DFD0CB81EF: public key "OpenSSL <openssl@openssl.org>" imported
    gpg: Total number processed: 1
    gpg:               imported: 1
  3. Verify the fingerprint of the imported key to ensure it matches OpenSSL’s official key:

    gpg --fingerprint openssl@openssl.org

    You should see output similar to the following:

    pub   rsa4096 2024-04-08 [SC] [expires: 2026-04-08]
          BA54 73A2 B058 7B07 FB27  CF2D 2160 94DF D0CB 81EF
    uid           [ unknown] OpenSSL <openssl@openssl.org>
  4. Finally, verify the OpenSSL source file against its signature:

    gpg --verify openssl-3.4.0.tar.gz.asc openssl-3.4.0.tar.gz

    You should see a confirmation similar to the output below:

    gpg: Signature made Tue 22 Oct 2024 12:27:03 PM UTC
    gpg:                using RSA key BA5473A2B0587B07FB27CF2D216094DFD0CB81EF
    gpg: Good signature from "OpenSSL <openssl@openssl.org>" [unknown]
    Note

    If you see a warning message about not having a trusted signature, it does not impact the validity of the signature:

    gpg: WARNING: This key is not certified with a trusted signature!
    gpg:          There is no indication that the signature belongs to the owner.
    Primary key fingerprint: BA54 73A2 B058 7B07 FB27  CF2D 2160 94DF D0CB 81EF

    The warning message appears because the OpenSSL signing key has not yet been marked as “trusted” in your GnuPG keyring.

Build OpenSSL

After verifying the source code, the next step is to build OpenSSL from source.

  1. Extract the downloaded OpenSSL archive:

    tar zxf openssl-3.4.0.tar.gz
  2. Change into the extracted OpenSSL source directory:

    cd openssl-3.4.0
  3. Configure the OpenSSL build, specifying the installation path as /opt and setting the appropriate runtime library search path:

    ./Configure --prefix=/opt '-Wl,-rpath,$(LIBRPATH)'
  4. Use make to compile the OpenSSL source code:

    make
    Note
    This process may take a few minutes depending on your system.
  5. Install the compiled OpenSSL files to the specified location:

    sudo make install
    Note
    This process may take a few minutes depending on your system.
  6. Verify that the correct version of OpenSSL is installed:

    /opt/bin/openssl version

    This should return the version number of the OpenSSL build you just installed to /opt/bin:

    OpenSSL 3.4.0 22 Oct 2024 (Library: OpenSSL 3.4.0 22 Oct 2024)
  7. Now check the active version via the basic openssl command:

    openssl version

    This should still show 1.1.1w, the default version bundled with Debian 11:

    OpenSSL 1.1.1w  11 Sep 2023

In order to complete the installation, you need to make sure that the version you installed in /opt/bin is used instead.

Add /opt/bin to Your PATH

Adjust your PATH environment variable to prioritize the /opt/bin directory.

  1. Open your ~/.bashrc file in a command line text editor such as nano:

    nano ~/.bashrc

    Append the following line to the end of the file:

    File: ~/.bashrc
    1
    
    export PATH=/opt/bin:$PATH

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

  2. Apply the changes:

    source ~/.bashrc
  3. Use the basic openssl command to recheck the active version of OpenSSL:

    openssl version

    The output should now show version 3.4.0, which you installed in /opt/bin:

    OpenSSL 3.4.0 3 Sep 2024 (Library: OpenSSL 3.4.0 3 Sep 2024)

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.

Install Dependencies

A couple of dependencies must be installed prior to oqs-provider, along with Git:

  1. First, change back into your user’s home directory:

    cd ~
  2. Install git, a distributed version control system that can manage code repositories:

    sudo apt install -y git
  3. Now install cmake, a cross-platform build system generator that helps automate the compilation and build process for software projects:

    sudo apt install -y cmake
  4. Finally, install ninja-build, a build system designed to run builds in parallel, which reduces the compilation time of large projects:

    sudo apt install -y ninja-build

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:

    env OPENSSL_ROOT=/opt CMAKE_PARAMS="-DOPENSSL_CRYPTO_LIBRARY=/opt/lib64/libcrypto.so" bash 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

Configure OpenSSL to Use the OQS Provider

  1. Use nano to edit the OpenSSL configuration file:

    sudo nano /opt/ssl/openssl.cnf

    Add the following lines at the end:

    File: /opt/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
    Note
    In this case, you are editing the /opt/ssl/openssl.cnf file, not the configuration file for the system OpenSSL.

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

Check Provider Version Information

  1. 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.4.0
        status: active
      oqsprovider
        name: OpenSSL OQS Provider
        version: 0.7.1-dev
        status: active

Install Nginx from Source

The version of Nginx available for Debian 11 uses OpenSSL version 1.1.1w. In order to use OpenSSL 3.x, you must build Nginx from source.

Fetch Nginx Source

  1. Before continuing, change back into your user’s home directory:

    cd ~
  2. Use wget to download the Nginx source files:

    wget https://nginx.org/download/nginx-1.27.2.tar.gz
  3. Also download the corresponding signature for verification:

    wget https://nginx.org/download/nginx-1.27.2.tar.gz.asc

Verify the Signature

  1. Download the public key:

    wget https://nginx.org/keys/pluknet.key
  2. Import the key:

    gpg --import pluknet.key
  3. Verify the signature:

    gpg --verify nginx-1.27.2.tar.gz.asc nginx-1.27.2.tar.gz

    If verification succeeds, you should see output similar to the following:

    gpg: Signature made Wed 02 Oct 2024 03:31:12 PM UTC
    gpg:                using RSA key D6786CE303D9A9022998DC6CC8464D549AF75C0A
    gpg:                issuer "s.kandaurov@f5.com"
    gpg: Good signature from "Sergey Kandaurov <s.kandaurov@f5.com>" [unknown]
    gpg:                 aka "Sergey Kandaurov <pluknet@nginx.com>" [unknown]
    gpg: WARNING: This key is not certified with a trusted signature!
    gpg:          There is no indication that the signature belongs to the owner.
    Primary key fingerprint: D678 6CE3 03D9 A902 2998  DC6C C846 4D54 9AF7 5C0A
    Note
    Nginx uses individual developer keys to sign its releases, so don’t be alarmed if you see unfamiliar names during verification. If verification fails, additional signing keys can be found at https://nginx.org/en/pgp_keys.html.

Install Dependencies

A couple of libraries are required before building Nginx:

  1. Install zlib1g-dev, a compression library for handling compressed content:

    sudo apt install -y zlib1g-dev
  2. Install libcre3 and libcre3-dev to support regular expressions, often used for URL matching:

    sudo apt install -y libpcre3 libpcre3-dev

Build Nginx

  1. Extract the source:

    tar zxf nginx-1.27.2.tar.gz
  2. Change into the extracted source directory:

    cd nginx-1.27.2
  3. Configure the build with the necessary flags:

    ./configure --with-cc-opt='-g -O2 -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' \
        --with-ld-opt='-Wl,-z,relro -Wl,-z,now -fPIC'      \
        --prefix=/opt                                      \
        --conf-path=/opt/nginx/nginx.conf              	\
        --http-log-path=/var/log/nginx/access.log      	\
        --error-log-path=/var/log/nginx/error.log      	\
        --lock-path=/var/lock/nginx.lock               	\
        --pid-path=/run/nginx.pid                      	\
        --modules-path=/opt/lib/nginx/modules              \
        --http-client-body-temp-path=/var/lib/nginx/body   \
        --http-fastcgi-temp-path=/var/lib/nginx/fastcgi    \
        --http-proxy-temp-path=/var/lib/nginx/proxy        \
        --http-scgi-temp-path=/var/lib/nginx/scgi          \
        --http-uwsgi-temp-path=/var/lib/nginx/uwsgi        \
        --with-compat                                  	\
        --with-debug                                   	\
        --with-http_ssl_module                         	\
        --with-http_stub_status_module                 	\
        --with-http_realip_module                      	\
        --with-http_auth_request_module                	\
        --with-http_v2_module                          	\
        --with-http_dav_module                         	\
        --with-http_slice_module                       	\
        --with-threads                                 	\
        --with-http_addition_module                    	\
        --with-http_gunzip_module                      	\
        --with-http_gzip_static_module                 	\
        --with-http_sub_module                         	\
        --with-pcre                                    	\
        --with-openssl-opt=enable-tls1_3               	\
        --with-ld-opt="-L/opt/lib64 -Wl,-rpath,/opt/lib64" \
        --with-cc-opt="-I/opt/include"

    Except for the destination prefix, this example uses the same configuration parameters as the binary package. This is to retain feature parity and integrate with system scripts. The last three options passed to the configure script are necessary to use the OpenSSL version built earlier.

  4. Compile Nginx:

    make
  5. Install Nginx:

    sudo make install
  6. Create the necessary directories for temporary file storage:

    sudo mkdir /var/lib/nginx
  7. Create a directory for additional configuration files:

    sudo mkdir /opt/nginx/conf.d

Configure Nginx

  1. Edit the main Nginx configuration file:

    sudo nano /opt/nginx/nginx.conf

    Add the following line to the top of the file to specify the user:

    File: /opt/nginx/nginx.conf
    1
    
    user www-data; #add this to the top of the file

    Locate the http block and add the highlighted lines to include configuration files in the /opt/nginx/nginx.conf directory:

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

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

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

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

    Give it the following contents:

    File: /opt/nginx/conf.d/pqc.conf
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    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.

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
    1. 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 systemd and Start Nginx

  1. Create a systemd service file for Nginx:

    sudo nano /etc/systemd/system/nginx.service

    Give it the following contents:

    File: /etc/systemd/system/nginx.service
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    
    [Unit]
    Description=The NGINX HTTP and reverse proxy server
    After=network.target remote-fs.target nss-lookup.target
    
    [Service]
    Type=forking
    PIDFile=/run/nginx.pid
    ExecStartPre=/opt/sbin/nginx -t
    ExecStart=/opt/sbin/nginx
    ExecReload=/opt/sbin/nginx -s reload
    ExecStop=/opt/sbin/nginx -s stop
    PrivateTmp=true
    
    [Install]
    WantedBy=multi-user.target

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

  2. Start the Nginx service:

    sudo service nginx start

Nginx should now be installed, configured, and running with OpenSSL 3.x support.

Verify Nginx Is Using Post-Quantum Algorithms

Run the openssl command with the flags shown below:

openssl s_client -groups X25519MLKEM768 -connect localhost:443

This command specifically checks for the X25519_Kyber768 algorithm during a TLS connection.

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.