Automated setup tool for Post-Quantum Cryptography (PQC) testing with nginx and curl
A Python-based automation tool for installing, configuring, and testing nginx-pqc and curl-pqc with support for:
- TLS 1.3 with Post-Quantum Key Exchange
- QUIC (HTTP/3) with Post-Quantum Key Exchange
- Hybrid curves (classical + PQC)
- Pure PQC curves (MLKEM512, MLKEM768, MLKEM1024)
Based on patterns from Cisco FTD PQC SSL Inspection test framework.
- Features
- Supported PQC Curves
- Requirements
- Installation
- Quick Start
- Usage Examples
- Configuration Options
- Testing
- Architecture
- Troubleshooting
- Contributing
- License
- β Automatic installation of nginx-pqc with QUIC/HTTP3 support
- β Automatic installation of OpenSSL 3.x with OQS provider
- β PQC-compatible certificate generation
- β nginx configuration templates for TLS and QUIC
- β Service management (start/stop/reload)
- β Port availability checking
- β Firewall configuration assistance
- β Automatic installation of curl-pqc with QUIC/HTTP3 support
- β Generated test scripts for TLS and QUIC
- β Support for multiple PQC curves in single test run
- β Verbose output with SSL/TLS details
- β HTTP/3 Alt-Svc support
- β Pure PQC: MLKEM512, MLKEM768, MLKEM1024
- β Hybrid: X25519MLKEM768, SecP256r1MLKEM768, SecP384r1MLKEM1024
- β TLS 1.3 with PQC key exchange
- β QUIC (HTTP/3) with PQC key exchange
- β Session resumption with 0-RTT
| Curve Name | Type | Security Level | Description |
|---|---|---|---|
| MLKEM512 | Pure PQC | 128-bit | NIST ML-KEM Level 1 |
| MLKEM768 | Pure PQC | 192-bit | NIST ML-KEM Level 3 (Recommended) |
| MLKEM1024 | Pure PQC | 256-bit | NIST ML-KEM Level 5 |
| X25519MLKEM768 | Hybrid | 192-bit | X25519 + MLKEM768 |
| SecP256r1MLKEM768 | Hybrid | 192-bit | P-256 + MLKEM768 |
| SecP384r1MLKEM1024 | Hybrid | 256-bit | P-384 + MLKEM1024 |
Recommended: Start with MLKEM768 or X25519MLKEM768 for balanced security and performance.
- OS: Linux (Ubuntu 20.04+, CentOS 8+, RHEL 8+)
- CPU: 4+ cores (for compilation)
- RAM: 4GB+ (for compilation)
- Disk: 5GB+ free space
- Root access: Required for installation
- Python 3.6+
- git
- cmake
- ninja-build
- gcc/g++
- OpenSSL development headers
Note: The script automatically installs dependencies on supported systems.
# Clone repository
git clone https://github.com/yourusername/PQC-TLS-QUIC-Simplifier.git
cd PQC-TLS-QUIC-Simplifier
# Run full installation (nginx-pqc + curl-pqc + OpenSSL)
sudo python3 pqc_setup.py --mode both --install-allThis will:
- Install system dependencies
- Build and install liboqs (Open Quantum Safe library)
- Build and install OpenSSL 3.x with OQS provider
- Build and install nginx with QUIC and PQC support
- Build and install curl with QUIC and PQC support
- Generate PQC certificates
- Configure nginx for TLS and QUIC
- Generate client test scripts
Installation time: ~20-30 minutes (depending on system)
# Configure nginx and generate test scripts (no installation)
sudo python3 pqc_setup.py --mode both --no-install# Remove all previous builds and reinstall from scratch
sudo python3 pqc_setup.py --mode both --install-all --cleanUse --clean when:
- Build failed midway and you need fresh start
- Switching OpenSSL versions
- Resolving dependency conflicts
- Starting over after errors
What --clean removes:
/tmp/pqc-build/*(all build artifacts)/opt/liboqs,/opt/openssl-pqc,/opt/nginx-pqc,/opt/curl-pqc/opt/nghttp3,/opt/ngtcp2
# Full setup with default curves (MLKEM768, X25519MLKEM768)
sudo python3 pqc_setup.py --mode both --install-all
# Setup with specific curves
sudo python3 pqc_setup.py --mode both --install-all \
--curves MLKEM768 MLKEM1024 X25519MLKEM768# Run generated TLS test script
~/PQC-TLS-QUIC-Simplifier/scripts/test_tls.shExpected output:
π Testing PQC TLS 1.3...
================================
Testing curve: MLKEM768
---
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* Server certificate: CN=pqc-test.local
* SSL-Session: Protocol: TLSv1.3
* Peer signing digest: SHA256
PQC TLS Test OK
Curve: mlkem768
Protocol: TLS 1.3
Cipher: TLS_AES_256_GCM_SHA384
# Run generated QUIC test script
~/PQC-TLS-QUIC-Simplifier/scripts/test_quic.shExpected output:
π Testing PQC QUIC (HTTP/3)...
================================
Testing curve: X25519MLKEM768
---
* Using HTTP/3
* Connected to pqc-test.local (127.0.0.1) port 443
* h3 [:method: GET]
PQC QUIC Test OK
Protocol: HTTP/3.0
Curve: X25519MLKEM768
sudo python3 pqc_setup.py \
--mode tls \
--install-all \
--curves MLKEM768 \
--server-name myserver.local \
--https-port 8443sudo python3 pqc_setup.py \
--mode quic \
--install-all \
--curves X25519MLKEM768 SecP256r1MLKEM768 \
--server-name quic-test.local \
--quic-port 443sudo python3 pqc_setup.py \
--mode both \
--install-all \
--curves MLKEM512 MLKEM768 MLKEM1024 \
X25519MLKEM768 SecP256r1MLKEM768 SecP384r1MLKEM1024 \
--server-name pqc-full.localsudo python3 pqc_setup.py \
--mode tls \
--curves MLKEM768 \
--ssl-protocols "TLSv1.3" \
--ssl-ciphers "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" \
--ssl-session-cache "shared:SSL:20m" \
--ssl-session-timeout "30m" \
--ssl-early-data on# No installation or root required
python3 pqc_setup.py \
--mode client \
--curves MLKEM768 X25519MLKEM768 \
--server-name existing-server.local# TLS 1.3 with MLKEM768
/opt/curl-pqc/bin/curl --tlsv1.3 \
--curves MLKEM768 \
--cacert /etc/nginx/pqc-certs/server.crt \
--verbose \
https://pqc-test.local:443/test
# QUIC (HTTP/3) with X25519MLKEM768
/opt/curl-pqc/bin/curl --http3 \
--curves X25519MLKEM768 \
--cacert /etc/nginx/pqc-certs/server.crt \
--verbose \
https://pqc-test.local:443/test| Argument | Default | Description |
|---|---|---|
--mode |
both |
Setup mode: tls, quic, both, or client |
--install-all |
- | Install nginx-pqc, curl-pqc, and dependencies |
--no-install |
- | Skip installation, configure only |
--http-port |
80 |
HTTP port (redirect to HTTPS) |
--https-port |
443 |
HTTPS port |
--quic-port |
443 |
QUIC (UDP) port |
--server-name |
pqc-test.local |
Server name |
--cert-dir |
/etc/nginx/pqc-certs |
Certificate directory |
--nginx-config-dir |
/etc/nginx |
nginx configuration directory |
--curves |
MLKEM768 X25519MLKEM768 |
PQC curves to enable |
--ssl-protocols |
TLSv1.3 |
SSL protocols |
--ssl-ciphers |
TLS_AES_256_GCM_SHA384:... |
SSL cipher suites |
--ssl-session-cache |
shared:SSL:10m |
SSL session cache |
--ssl-session-timeout |
10m |
SSL session timeout |
--ssl-session-tickets |
on |
SSL session tickets |
--ssl-early-data |
off |
SSL early data (0-RTT) |
# Override binary paths
export CURL_PQC_BINARY="/custom/path/curl"
export NGINX_PQC_BINARY="/custom/path/nginx"
export OPENSSL_BINARY="/custom/path/openssl"After setup, test scripts are generated in ~/PQC-TLS-QUIC-Simplifier/scripts/:
- test_tls.sh - Test TLS 1.3 with all configured curves
- test_quic.sh - Test QUIC (HTTP/3) with all configured curves
# Run all TLS tests
~/PQC-TLS-QUIC-Simplifier/scripts/test_tls.sh
# Run all QUIC tests
~/PQC-TLS-QUIC-Simplifier/scripts/test_quic.sh# Test configuration
/opt/nginx-pqc/sbin/nginx -t
# View running processes
ps aux | grep nginx
# Check listening ports
netstat -tulpn | grep nginx# Error log
tail -f /var/log/nginx/error.log
# Access log
tail -f /var/log/nginx/access.log# Basic connectivity
curl -k https://pqc-test.local/test
# Check HTTP/3 support
curl -k --http3 https://pqc-test.local/test# Capture TLS handshake with tcpdump
sudo tcpdump -i any -s 0 -w pqc-capture.pcap port 443
# Analyze with Wireshark or tshark
tshark -r pqc-capture.pcap -Y "tls.handshake.type == 1" -T fields \
-e tls.handshake.extensions.supported_groupsβββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PQC-TLS-QUIC-Simplifier β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β Installation Phase (Optional) β
βββββββββββββββββββββββββββββββββββββββββββββββββ€
β 1. System Dependencies (gcc, cmake, etc.) β
β 2. liboqs (Open Quantum Safe) β
β 3. OpenSSL 3.x + OQS Provider β
β 4. nginx with QUIC + PQC β
β 5. curl with QUIC + PQC β
βββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β Configuration Phase β
βββββββββββββββββββββββββββββββββββββββββββββββββ€
β 1. Generate PQC Certificates β
β 2. Create nginx Config (TLS/QUIC) β
β 3. Start nginx Service β
β 4. Generate Test Scripts β
βββββββββββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββ
β Testing Phase β
βββββββββββββββββββββββββββββββββββββββββββββββββ€
β TLS 1.3: curl-pqc β nginx-pqc (TCP 443) β
β QUIC: curl-pqc β nginx-pqc (UDP 443) β
β with PQC key exchange β
βββββββββββββββββββββββββββββββββββββββββββββββββ
PQC-TLS-QUIC-Simplifier/
βββ pqc_setup.py # Main setup script
βββ README.md # This file
βββ LICENSE # License file
βββ .gitignore # Git ignore patterns
β
βββ certs/ # Generated certificates (runtime)
β βββ server.crt
β βββ server.key
β
βββ configs/ # Generated nginx configs (runtime)
β βββ nginx.conf # TLS configuration
β βββ nginx-quic.conf # QUIC configuration
β
βββ scripts/ # Generated test scripts (runtime)
β βββ test_tls.sh # TLS test script
β βββ test_quic.sh # QUIC test script
β
βββ tests/ # Example test files
βββ index.html # Test HTML file
/opt/
βββ openssl-pqc/ # OpenSSL with PQC support
β βββ bin/openssl
β βββ lib/ossl-modules/oqsprovider.so
β
βββ liboqs/ # Open Quantum Safe library
β βββ include/
β βββ lib/
β
βββ nginx-pqc/ # nginx with QUIC + PQC
β βββ sbin/nginx
β βββ conf/
β
βββ curl-pqc/ # curl with QUIC + PQC
βββ bin/curl
/etc/nginx/
βββ nginx.conf # TLS configuration
βββ nginx-quic.conf # QUIC configuration
βββ pqc-certs/ # PQC certificates
βββ server.crt
βββ server.key
Symptom: Address already in use error
Solution:
# Check what's using the port
sudo netstat -tulpn | grep :443
# Stop conflicting service
sudo systemctl stop apache2 # or nginxSymptom: SSL certificate problem: self signed certificate
Solution:
# Use --insecure flag for testing
curl --insecure https://pqc-test.local/test
# Or add to system CA store
sudo cp /etc/nginx/pqc-certs/server.crt /usr/local/share/ca-certificates/
sudo update-ca-certificatesSymptom: nginx configuration test fails
Solution:
# Check configuration syntax
/opt/nginx-pqc/sbin/nginx -t
# Check error log
tail -f /var/log/nginx/error.log
# Verify permissions
ls -la /etc/nginx/pqc-certs/Symptom: curl falls back to TCP
Solution:
# Verify UDP port is open
sudo ufw allow 443/udp
# Check nginx QUIC support
/opt/nginx-pqc/sbin/nginx -V | grep quic
# Test with tcpdump
sudo tcpdump -i any -n udp port 443Symptom: SSL: no ciphers available or curve errors
Solution:
# Verify OpenSSL OQS provider
/opt/openssl-pqc/bin/openssl list -providers
# Check available curves
/opt/openssl-pqc/bin/openssl list -kem-algorithms
# Rebuild with latest liboqs
sudo python3 pqc_setup.py --install-allSymptom: Compilation errors
Solution:
# Install missing dependencies
sudo apt-get install build-essential libssl-dev zlib1g-dev
# Clean reinstall (recommended)
sudo python3 pqc_setup.py --mode both --install-all --cleanThe --clean flag automatically:
- Removes all build artifacts
- Removes all installed components
- Starts fresh installation
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Support for additional PQC algorithms (Falcon, Dilithium signatures)
- Docker container support
- Automated testing framework
- Performance benchmarking tools
- Additional platform support (macOS, Windows WSL)
- Integration with Let's Encrypt for PQC certificates
This project is licensed under the MIT License - see the LICENSE file for details.
- Open Quantum Safe (OQS) - liboqs and oqs-provider
- NIST PQC Project - ML-KEM standardization
- nginx - Web server with QUIC support
- curl - HTTP client with QUIC support
- Cisco FTD SSL Inspection Team - Test framework patterns and PQC testing methodology
- NginxTLSSimplifier - Inspiration for this project
- OQS-demos - Additional PQC examples
For questions, issues, or feature requests:
- GitHub Issues: Report a bug or request a feature
- Email: your.email@example.com
Made with β€οΈ for the Post-Quantum future