Tutorial

Building a quantum-safe web application based on a quantum-safe version of OpenSSL

Learn how to build a quantum-safe web application using Apache HTTPD as the web server and proxying client requests through HAProxy

By

Mariam John

Quantum computing is a relatively new and emerging technology with the potential to solve complex problems that are too difficult for classical computers. Although this opens up a lot of opportunities for the greater good, it also poses possible risks to our current systems and communications, especially in the area of cybersecurity.

Today's cryptographic systems that form the building blocks of securing our networks and communications are built based on algorithms and processes that could one day be broken by a cryptographically relevant quantum computer. Quantum-safe cryptography is an active area of research and development working to find new algorithms and prototype solutions that are quantum safe.

In this tutorial, you will learn how to build a quantum-safe web application based on a quantum-safe version of OpenSSL, using Apache HTTPD as the web server and proxying client requests through HAProxy which acts as a reverse proxy. To set up our environment, we have used 2 servers: one to setup and install an Apache server and the other to install HAProxy. You could also have an optional server to act as a root certificate authority (CA) for key and certificate management.

We will be using the lattice-based algorithms CRYSTALS-Dilithium for digital signature algorithm (DSA) and CRYSTALS-Kyber as the Key Encapsulation Mechanism algorithm (KEM).

Building a quantum-safe version of OpenSSL requires that you configure OpenSSL to use implementations of quantum-safe algorithms. OpenSSL provides a mechanism called providers which provides a pluggable model for third-party providers to add their implementations of new algorithms. We will be using the OQS(Open Quantum Safe) provider in this implementation to add quantum safe support to OpenSSL.

We will then go on to build Apache HTTPD and HAProxy using this quantum-safe version of OpenSSL. The Open Quantum Safe(OQS) project is an open source project whose objective is to encourage research and development in the field of quantum safe cryptography. This includes developing implementations of quantum safe algorithms and developing prototypes of applications using these quantum safe implementations.

liboqs is an open source library that is part of the OQS project and focuses on developing implementations for quantum-safe algorithms for key exchange and digital signatures used in public key cryptography. The OQS project relies on National Institute of Standards and Technology's (NIST) "Post-Quantum Cryptography Standardization (PQCS)" to identify quantum-resistant algorithms to use.

Setting up your development environment

For this demo environment, we have used 2 ubuntu 22.04(x86_64) LTS servers to install Apache HTTPD v2.4.57 and HAProxy v2.8.0. The following figure shows a layout of a sample environment.

Sample demo env

The foundation for building a quantum-safe application as shown in this tutorial is to build a quantum-safe version of OpenSSL first, and then build HAProxy and Apache HTTPD using this quantum-safe version of OpenSSL. To see how to build and install OpenSSL to use quantum safe algorithms, refer to this quantum-safe OpenSSL tutorial, which uses the liboqs library and oqs-provider library to build OpenSSL v3.x.

When building a quantum-safe version of OpenSSL, make sure you build it in a location that can be accessed during the HTTPD and HAProxy builds by specifying the OPENSSL_PATH variable.

For this demo, we will be creating and using self-signed certificates using dilithium5(which is a signature algorithm under the CRYSTALS-Dilithium category) to create the certificate authority(CA) and server certificates. To establish a TLSv1.3 session using quantum-safe KEM algorithms, we will be using kyber768 and p384_kyber768 to activate Kyber768 and its hybrid variant. Other supported quantum-safe algorithms (KEM/DSA) that are implemented by the oqs-provider can be used to create certificates and for establishing TLS sessions.

Steps

Before you go ahead and work through the steps in this tutorial, make sure you have followed the instructions in this quantum-safe OpenSSL tutorial to build and install a quantum-safe version of OpenSSL. This prerequisite step must be done on the servers where you will be building HAProxy and Apache HTTP.

The instructions in this tutorial have been divided into five steps. Step 1 contains instructions to create a non-root user on Ubuntu. Since we will be using a non-root user to build HAProxy and Apache HTTPD, Step 1 also needs to be completed as a pre-req on both servers. Steps 3 & 4 are related to building Apache HTTPD and Step 5 contains instructions to build and install HAProxy.

  • Step 1: Create a non-root user on Ubuntu (on HAProxy & Apache HTTPD servers)
  • Step 2: Build and install quantum-safe version of OpenSSL by following the quantum-safe OpenSSL tutorial (on HAProxy & Apache HTTPD servers)
  • Step 3: Create CA and server certificates using quantum-safe algorithms (on Apache HTTPD server)
  • Step 4: Build and install quantum-safe version of Apache HTTPD (on Apache HTTPD server)
  • Step 5: Build and install quantum-safe version of HAProxy (on HAProxy server)

Step 1. Create a non-root user on Ubuntu (on HAProxy & Apache HTTPD servers)

To create a non-root user in Ubuntu, log in to the system using the root user and run the following commands:

  • Add a new user account to the system and enter a new password for the user when prompted. The prompts for changes to user information can be ignored by hitting ENTER as it is optional.

     adduser <username>
    
  • Add the new user to the sudo group:

      usermod -aG sudo <username>
    
  • Switch to the new user:

      su - <username>
    

Step 2. Build and install quantum-safe version of OpenSSL (on HAProxy & Apache HTTPD servers)

Follow the steps in the quantum-safe OpenSSL tutorial.

If you prefer, you can define the environment variables which will be used throughout this tutorial in the .bashrc file:

vi $HOME/.bashrc

Enter the following lines, and then save and exit:

  export WORKSPACE=$HOME/quantumsafe
  export BUILD_DIR=$WORKSPACE/build
  export OPENSSL_CONF=$BUILD_DIR/ssl/openssl.cnf
  export OPENSSL_MODULES=$BUILD_DIR/lib

Run the following command:

source $HOME/.bashrc

Step 3. Create self-signed keys and certificates using quantum-safe algorithms (on Apache HTTPD server)

After you've built and installed OpenSSL to use quantum-safe algorithms by completing this quantum-safe OpenSSL tutorial, you can create self-signed keys and certificates for the backend HTTPD server.

Before creating the self-signed keys and certificates, verify the liboqs-provider is correctly installed and configured with OpenSSL:

$BUILD_DIR/bin/openssl list -providers -verbose -provider oqsprovider

This command should list the default provider and lib-oqs provider similar to the following sample output.

Sample output listing openssl providers

First, create keys and certificates for the CA and the server using quantum-safe algorithms.

  1. Create the CA key and certificate. We will be using the signature algorithm dilithium5 to create the CA key. For the subject of the certificate, we set the following value: "/CN=oqstest CA" (It can be any value, as long as it is not the same common name as the server certificate).

     cd $WORKSPACE
     $BUILD_DIR/bin/openssl req -x509 -new -newkey dilithium5 -keyout CA.key -out CA.crt -nodes -subj "/CN=oqstest CA" -days 365 -config $BUILD_DIR/ssl/openssl.cnf
    
  2. Create the server key and certificate. Replace the hostname defined in the subj parameter to the correct hostname for your server server (for example, -subj “/CN=c92989v1.ibm.com”).

     $BUILD_DIR/bin/openssl req -new -newkey dilithium5 -keyout server.key -out server.csr -nodes -subj "/CN=<hostname>" -config $BUILD_DIR/ssl/openssl.cnf
     $BUILD_DIR/bin/openssl x509 -req -in server.csr -out server.crt -CA CA.crt -CAkey CA.key -CAcreateserial -days 365
    
  3. Create the certificate chain.

     cat server.crt > qsc-ca-chain.crt
     cat CA.crt >> qsc-ca-chain.crt
    

    Next, verify that the TLS connection is using the OpenSSL certificates that you just created. To test this, we will start a simple HTTP server using an openssl s_server session.

  4. Start the TLS server provided by OpenSSL in a separate terminal.

     $BUILD_DIR/bin/openssl s_server -cert $WORKSPACE/server.crt -key $WORKSPACE/server.key -www -tls1_3 -CAfile $WORKSPACE/CA.crt -curves kyber512:p521_kyber1024
    
  5. From the original terminal, start an openSSL client session to test the TLS connection to the openssl s_server session started above. The output should contain the certificate chain and server certificate as shown below. Press Ctrl + C to exit:

     $BUILD_DIR/bin/openssl s_client  -CAfile $WORKSPACE/qsc-ca-chain.crt -groups p521_kyber1024
    

    You should see the output similar to the one in the figure below, displaying the quantum-safe KEM and signature algorithms used.

    SSL client output

  6. Test the TLS connection by sending curl requests to the s_server session. (Replace the <hostname> with the hostname used in the subj parameter in step 3.2 to create the server certificate.)

     $BUILD_DIR/bin/curl -v --cacert $WORKSPACE/qsc-ca-chain.crt --curves kyber512:p521_kyber1024 https://<hostname>:4433
    

    You should see the output similar to the one in the figure below, displaying the quantum-safe KEM and signature algorithms used.

    SSL curl output

  7. Stop the TLS server that you started in Step 3.4 by entering Ctrl + C.

Step 4. Build and install quantum-safe Apache HTTPD (on Apache HTTPD server)

In this step, we will build, install, and configure Apache HTTPD, a free, open-source, web based HTTP server. We will build Apache HTTPD using the quantum-safe OpenSSL version we built earlier and configure the server to use the certificates we created in the previous step. We will test this setup by sending curl requests to the HTTPD server and verify the TLS connection.

  1. Build and install Apache HTTPD using quantum-safe OpenSSL.

     export HTTPD_PATH=$WORKSPACE/httpd
     export HTTPD_VERSION=2.4.57
     export APR_VERSION=1.7.4
     export APRU_VERSION=1.6.3
     export APR_MIRROR="https://dlcdn.apache.org"
    

    Compiling HTTPD requires apr and apr-util (Apache Portable Runtime) to be already installed on the system. The commands below install these requirements and also builds and installs HTTPD. (For more information about the commands, refer to the official documentation)

     cd $WORKSPACE
    
     # Install pre-req libraries required for building HTTPD.
     sudo apt install -y libexpat1-dev libpcre3 libpcre3-dev
    
     git clone --branch 2.4.57 https://github.com/apache/httpd.git ${HTTPD_PATH}-${HTTPD_VERSION}
     cd ${HTTPD_PATH}-${HTTPD_VERSION}
    
     # Download both APR and APR-Util from Apache APR, unpack them into
     # `${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr` and
     # `${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr-util` respectively.
     mkdir srclib/apr
     mkdir srclib/apr-util
     wget https://dlcdn.apache.org/apr/apr-1.7.4.tar.gz && tar xzvf apr-1.7.4.tar.gz -C ${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr --strip-components 1
     wget https://dlcdn.apache.org/apr/apr-util-1.6.3.tar.gz && tar xzvf apr-util-1.6.3.tar.gz -C ${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr-util --strip-components 1
    
     ./buildconf --with-apr=${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr --with-apr-util=${HTTPD_PATH}-${HTTPD_VERSION}/srclib/apr-util
    
    ./configure --with-included-apr --prefix=${HTTPD_PATH} \
          --enable-debugger-mode \
          --enable-ssl --with-ssl=${BUILD_DIR} \
          --enable-ssl-staticlib-deps \
          --enable-mods-static=ssl && \
          make && make install;
    
  2. Configure HTTPD server to handle HTTP requests

    In this step we need to update the httpd configuration file to handle HTTP requests. The changes shown below are the updates made to the applicable configuration options in httpd.conf. We can use the provided/default values for the rest of the configuration options.

    When starting the HTTPD server as a non-root user, there are couple of things to note:

    • All ports that the user listens to must be greater than 1024
    • All directories and files that the server creates or edits should have write permission for the non-root user

      Edit the HTTPD configuration file located at $HTTPD_PATH/conf/httpd.conf (search for the configuration options listed below in the httpd.conf file and make the updates). In this file we update the following configurations (make sure to replace the entries within <> with the correct values for your environment):

      • Listen - port that HTTPD server listens to for HTTP requests
      • User and Group - non-root user and group that is used to run the HTTP server
      • ServerName - hostname of the HTTPD server and port number > 1024 to listen for http requests
      • DocumentRoot and Directory - location of the index.html to serve when the HTTPD server receives HTTP requests. The directories defined below will be created in the next step along with a new index.html.
      Listen <2080>
      User <username>
      Group <username>
      ServerName <c92989v1.ibm.com>:<2080>
      DocumentRoot "</home/username/quantumsafe/httpd/htdocs/mydocs>"
      <Directory "</home/username/quantumsafe/httpd/htdocs/mydocs>">
       Options Indexes FollowSymLinks
       AllowOverride None
       Require all granted
      </Directory>
      

      Create the following directory that will host the document (index.html) which will be served when HTTP requests are made.

        mkdir $HTTPD_PATH/htdocs/mydocs
        vi  $HTTPD_PATH/htdocs/mydocs/index.html
      

      Enter anything you want to display in the index.html.

      <html><body><h1>Enter anything here!!</h1></body></html>
      

      Start the HTTPD server:

      $HTTPD_PATH/bin/apachectl -k start
      

      Test that HTTP requests work(Replace the <hostname>:<port number> with the ServerName configuration option specified in the httpd configuration file above: http://c92989v1.ibm.com:2080). You should see the text entered in the index.html displayed here when the curl requests are made.

      $BUILD_DIR/bin/curl http://<hostname>:<port number>
      

Step 5. Build and install quantum-safe HAProxy

HAProxy is a very popular open source based reverse proxy offering load balancing capabilities for both TCP and HTTP traffic. In addition to acting as a load balancer, it also helps secure traffic using TLS through techniques like SSL Passthrough or SSL termination. In SSL termination, the traffic encryption/decryption is handled at the HAProxy side(edge proxy), allowing unencrypted traffic to flow to the backend web servers. The TLS certificates of backend servers can also be managed at the HAProxy side. In the SSL Passthrough case, HAProxy just allows the encrypted traffic to pass through it without making any changes to the traffic flowing. In this case, the backend servers deal with encrypting and decrypting the traffic.

In this step, we will show you how to build HAProxy using quantum-safe enabled OpenSSL and configure HAProxy to perform SSL termination. (Before working on this step, make sure you have completed all the pre-reqs.)

We will install and run HAProxy as a non-root user for the purposes of this tutorial. When starting the HAProxy server as a non-root user, there are couple of things to note:

  • All ports that the user listens to must be greater than 1024
  • All directories and files that the server creates or edits should have write permission for the non-root user

  • Build HAProxy using quantum-safe OpenSSL.

     cd $WORKSPACE
    
     git clone --branch v2.8.0 https://github.com/haproxy/haproxy.git
     cd $WORKSPACE/haproxy
    
     make TARGET=generic \
           SSL_INC=$BUILD_DIR/include \
           SSL_LIB=$BUILD_DIR/lib64 \
           USE_OPENSSL=1
    
  • Copy the server and CA certificates from the Apache server to the HAProxy server side:

    • Create a directory to store the server certificate:

      mkdir $WORKSPACE/haproxy/certs; cd $WORKSPACE/haproxy/certs
      
    • Copy server certificates from the Apache server to the HAProxy server((server.crt, server.key, qsc-ca-chain.crt)). Replace the <username>:<hostname> with the non-root user we created earlier and the hostname of the Apache HTTPD server from where we want to fetch the certificates:

      scp <username>@<hostname>:$WORKSPACE/server.crt .
      scp <username>@<hostname>:$WORKSPACE/server.key .
      scp <username>@<hostname>:$WORKSPACE/qsc-ca-chain.crt .
      
    • Place both the server key and certificate in a PEM formatted file and update the permissions of the file:

      cat server.crt server.key >> server.pem
      chmod 755 server.pem
      
  • Create a configuration file for HAProxy. The HAProxy configuration file consists of mainly four sections: global, default, frontend and backend.

    The global section defines the configurations that affect the overall working and performance of the HAProxy service. For example, some of the settings we define in this section include where to direct log messages, maximum connections that HAProxy will accept, user/group settings to tell HAProxy to drop privileges after initialization and stats setting to enable the Runtime API which can be used to dynamically configure HAProxy.

    The default section defines the default settings for configurations related to how HAProxy receives and processes client requests. For example, the default settings for timeouts, maxconnections, mode (tcp or http), etc. The frontend section is used to set configurations related to where a user can send client requests to. This is useful when HAProxy is used as a reverse proxy to send client requests to backend servers. The backend section defines configurations related to the backend server that HAProxy will send the client requests to. For example, in the case of SSL termination, HAProxy terminates the SSL connection based on the configuration specified in the frontend section bind <ip>:<port> ssl crt and can inspect and modify things like HTTP headers and route traffic to different backend servers based on URL. The HAProxy documentation provides details about the different configuration options, if interested.

    Below is the HAProxy configuration file for enabling SSL termination by HAProxy. The SSL connection will be terminated at the edge proxy(HAProxy) and unencrypted traffic will be sent to the backend server(Apache HTTPD).

    • Create a new configuration file for HAProxy:

        cd $WORKSPACE/haproxy
        vi haproxy_ssl_termination.cfg
      
    • Copy and paste the configuration below into your HAProxy configuration file (make sure to replace the entries within <> with the correct values for your environment):

      • In the frontend section, you can specify any port > 1024 to handle http request (e.g: bind *:8080 and https request(e.g: bind *:8043)
      • In the frontend section, make sure you specify the correct location of the server.pem file at the HAProxy side as specified in the bind *:8043 parameter
      • In the backend section, change the hostname as specified in the server parameter to reflect your HTTPD ipaddress, and port number to reflect the port number that the HTTPD server is listening to for HTTP requests. (Format is: `server :)
      global
        maxconn 50000
        log         127.0.0.1:2514 local2
        ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.3
      
      defaults
         mode                    http
         log                     global
         timeout connect         10s
         timeout client          1m
         timeout server          1m
      
      frontend  web-frontend
         bind *:<8080>
         bind *:<8043> ssl curves kyber1024:kyber768:kyber512:p521_kyber1024 crt </home/username/quantumsafe/haproxy/certs/server.pem>
         http-request redirect scheme https unless { ssl_fc }
         default_backend web-backend
      
      backend web-backend
         balance     roundrobin
         server <c92989v1> <9.30.26.134:2080>
      
      listen stats
         bind *:9201
         mode http
         stats enable
         stats uri /
      
  • Start HAProxy server in the background.

     ./haproxy -f haproxy_ssl_termination.cfg &
    
  • Connect to the HAProxy server and test the SSL connection. (The hostname must be that of the HAProxy server and the port number is the SSL port it is listening to for HTTPS requests.)

     $BUILD_DIR/bin/curl https://<hostname>:<8043> -v -k --curves kyber512:p521_kyber1024
    

    haproxy-ssl-termination

    You should also see the quantum-safe algorithms used to encrypt this end-to-end TLS connection.

  • To stop the HAProxy server, run the command fg. This brings the HAProxy server running as a background process to the foreground. Run Ctrl + C to exit the process.

Summary and next steps

In this tutorial, we demonstrated how to build a quantum-safe web application using a quantum-safe version of OpenSSL, HAProxy, and Apache HTTPD server. We also demonstrated how to test a secure, end-to-end communication using quantum-safe algorithms.

If you are interested in looking at other protocols like SSH to understand how to make that protocol quantum safe, refer to this quantum-safe SSH tutorial.

You can also learn more about quantum-safe cryptography here, and explore more details in our developer's course on quantum-safe cryptography, “A practical introduction to quantum-safe cryptography”.

Acknowledgements

Thanks to Nigel Jones, Martin Schmatz, Paul Schweigert, and Alex Bozarth for their review and feedback.