Quick Start
Post-Quantum X.509 PKI in Go
QPKI is a quantum-safe PKI toolkit to help organizations prepare for post-quantum cryptography (PQC) with interoperable, standards-compliant certificates.
For education and prototyping — Learn PKI concepts, experiment with PQC migration, and test crypto-agility. See Qlab for step-by-step tutorials.
Features
Section titled “Features”- State-of-the-art X.509 certificates (RFC 5280 compliant)
- Post-Quantum Cryptography (PQC) support via ML-DSA, SLH-DSA and ML-KEM
- CSR generation for all algorithms including RFC 9883 ML-KEM attestation
- Catalyst certificates (ITU-T X.509 Section 9.8) - dual keys via extensions
- Composite certificates (IETF draft-13, DRAFT) - dual keys bound together
- Hybrid certificates (classical + PQC via combined or separate modes)
- SSH Certificates (OpenSSH format) - user and host certificate issuance (classical algorithms)
- CMS Signatures & Encryption (RFC 5652) - sign and encrypt with PQC
- Crypto-agility - seamless migration between algorithms (ECDSA → ML-DSA)
- Profiles (certificate templates) - define certificate policies in YAML
- Credentials - group certificates with coupled lifecycle
- HSM support via PKCS#11
- Cross-validated with external implementations (OpenSSL, BouncyCastle)
- CLI-first - simple, scriptable, no database required
- PQC via Cloudflare CIRCL — FIPS 203/204/205 implementations, NIST ACVP test vectors validated
- Pure Go by default - CGO optional (only for HSM/PKCS#11)
Supported Algorithms
Section titled “Supported Algorithms”Classical
Section titled “Classical”| Algorithm | Security | Notes |
|---|---|---|
| ECDSA (P-256, P-384, P-521) | ~128/192/256-bit | NIST curves, P-384 recommended |
| EdDSA (Ed25519, Ed448) | ~128/224-bit | Fast, constant-time |
| RSA (2048, 4096) | ~112/140-bit | Legacy compatibility |
EC keys support both ECDSA (signature) and ECDH (key agreement) depending on certificate keyUsage.
Post-Quantum
Section titled “Post-Quantum”| Algorithm | Security | Notes |
|---|---|---|
| ML-DSA-44/65/87 | NIST Level 1/3/5 | FIPS 204, lattice-based |
| SLH-DSA-128/192/256 | NIST Level 1/3/5 | FIPS 205, hash-based |
| ML-KEM-512/768/1024 | NIST Level 1/3/5 | FIPS 203, key encapsulation |
Classical security levels reflect resistance to classical attacks only. Post-quantum algorithms are designed to remain secure against quantum adversaries.
Installation
Section titled “Installation”Requirements
Section titled “Requirements”- Go 1.25 or later (only for building from source)
- No CGO required for standard usage
- CGO required only for HSM/PKCS#11 support (optional)
- No external dependencies (OpenSSL not required)
Download pre-built binaries (recommended)
Section titled “Download pre-built binaries (recommended)”Download the latest release for your platform from GitHub Releases.
Linux / macOS:
# Download (replace VERSION, OS, and ARCH as needed)curl -LO https://github.com/remiblancher/qpki/releases/latest/download/qpki_VERSION_OS_ARCH.tar.gz
# Extracttar -xzf qpki_*.tar.gz
# Installsudo mv qpki /usr/local/bin/
# Verifyqpki --versionAvailable platforms:
| OS | Architecture | File |
|---|---|---|
| Linux | amd64 | qpki_VERSION_linux_amd64.tar.gz |
| Linux | arm64 | qpki_VERSION_linux_arm64.tar.gz |
| macOS | Intel | qpki_VERSION_darwin_amd64.tar.gz |
| macOS | Apple Silicon | qpki_VERSION_darwin_arm64.tar.gz |
| macOS | Universal | qpki_VERSION_darwin_all.tar.gz |
| Windows | amd64 | qpki_VERSION_windows_amd64.zip |
Linux packages:
# Debian/Ubuntusudo dpkg -i qpki_VERSION_linux_amd64.deb
# RHEL/Fedorasudo rpm -i qpki_VERSION_linux_amd64.rpmInstall via Homebrew (macOS)
Section titled “Install via Homebrew (macOS)”brew tap remiblancher/qpkibrew install qpkiVerify release signatures
Section titled “Verify release signatures”All releases are signed with GPG. To verify:
# Import public keygpg --keyserver keyserver.ubuntu.com --recv-keys 39CD0BF9647E3F56
# Download checksums and signaturecurl -LO https://github.com/remiblancher/qpki/releases/download/vX.Y.Z/checksums.txtcurl -LO https://github.com/remiblancher/qpki/releases/download/vX.Y.Z/checksums.txt.sig
# Verify signaturegpg --verify checksums.txt.sig checksums.txtBuild from source
Section titled “Build from source”Requires Go 1.25 or later.
# Clone and buildgit clone https://github.com/remiblancher/qpki.gitcd qpkigo build -o qpki ./cmd/qpki
# Or install directly to GOPATH/bingo install github.com/remiblancher/qpki/cmd/qpki@latestVerify installation
Section titled “Verify installation”qpki versionqpki --helpQuick Start
Section titled “Quick Start”Initialize a Root CA
Section titled “Initialize a Root CA”# Create a CA with ECDSA P-384 (recommended)qpki ca init --profile ec/root-ca --ca-dir ./root-ca --var cn="My Root CA"# → root-ca/{ca.crt, private/ca.key, certs/, crl/, index.txt, serial}
# Create a hybrid CA (ECDSA + ML-DSA, ITU-T X.509 Section 9.8)qpki ca init --profile hybrid/catalyst/root-ca --ca-dir ./hybrid-ca --var cn="Hybrid Root CA"
# Create a pure PQC CA (ML-DSA-87)qpki ca init --profile ml/root-ca --ca-dir ./pqc-ca --var cn="PQC Root CA"Create a Subordinate CA
Section titled “Create a Subordinate CA”# Create a subordinate/issuing CA signed by the rootqpki ca init --profile ec/issuing-ca --ca-dir ./issuing-ca \ --parent ./root-ca --var cn="Issuing CA"This creates a complete CA structure with:
ca.crt- Subordinate CA certificatechain.crt- Full certificate chain (sub CA + root)private/ca.key- Subordinate CA private key
Generate Keys
Section titled “Generate Keys”Generate private key files. The public key is mathematically derived from the private key and can be extracted using qpki key pub.
# Generate an ECDSA keyqpki key generate --algorithm ecdsa-p256 --out key.pem
# Generate an ML-DSA-65 (PQC lattice-based) keyqpki key generate --algorithm ml-dsa-65 --out ml-dsa-key.pem
# Generate an SLH-DSA-128f (PQC hash-based) keyqpki key generate --algorithm slh-dsa-128f --out slh-dsa-key.pem
# Generate with passphrase protectionqpki key generate --algorithm ecdsa-p384 --out key.pem --passphrase mysecret
# Extract public key from private keyqpki key pub --key key.pem --out key.pubGenerate Certificate Signing Requests
Section titled “Generate Certificate Signing Requests”When using --keyout, the private key is generated alongside the CSR. Use --key to create a CSR from an existing key.
# Generate NEW key pair + CSRqpki csr gen --algorithm ecdsa-p256 --keyout server.key --cn server.example.com --out server.csr
# CSR from EXISTING key (no key generation)qpki csr gen --key existing.key --cn server.example.com --out server.csr
# PQC CSR (ML-DSA)qpki csr gen --algorithm ml-dsa-65 --keyout mldsa.key --cn alice@example.com --out mldsa.csr
# ML-KEM CSR with RFC 9883 attestationqpki csr gen --algorithm ml-kem-768 --keyout kem.key --cn alice@example.com \ --attest-cert sign.crt --attest-key sign.key --out kem.csr
# Hybrid CSR (ECDSA + ML-DSA dual signatures)qpki csr gen --algorithm ecdsa-p256 --keyout classical.key \ --hybrid ml-dsa-65 --hybrid-keyout pqc.key --cn example.com --out hybrid.csrIssue Certificates
Section titled “Issue Certificates”Certificates are always issued from a CSR (Certificate Signing Request).
For direct issuance with key generation, use qpki credential enroll instead.
# From classical CSR with variablesqpki cert issue --ca-dir ./myca --profile ec/tls-server \ --csr server.csr --out server.crt \ --var cn=api.example.com \ --var dns_names=api.example.com,api-v2.example.com
# Using a variables fileqpki cert issue --ca-dir ./myca --profile ec/tls-server \ --csr server.csr --var-file vars.yaml
# From PQC signature CSR (ML-DSA, SLH-DSA)qpki cert issue --ca-dir ./myca --profile ml/tls-server-sign \ --csr mldsa.csr --out server.crt \ --var cn=pqc.example.com
# From ML-KEM CSR (requires RFC 9883 attestation for verification)qpki cert issue --ca-dir ./myca --profile ml-kem/client \ --csr kem.csr --out kem.crt \ --attest-cert sign.crt --var cn=client@example.com
# From Hybrid CSR (classical + PQC dual signatures)qpki cert issue --ca-dir ./myca --profile hybrid/catalyst/tls-server \ --csr hybrid.csr --out server.crt \ --var cn=hybrid.example.comInspect & Verify
Section titled “Inspect & Verify”# Show certificate detailsqpki inspect certificate.crt
# Show key informationqpki inspect private-key.pem
# Verify certificate chainqpki cert verify server.crt --ca ./myca/ca.crt
# Verify with CRL revocation checkqpki cert verify server.crt --ca ./myca/ca.crt --crl ./myca/crl/ca.crl
# List all issued certificatesqpki cert list --ca-dir ./myca
# List only valid certificatesqpki cert list --ca-dir ./myca --status validSign & Encrypt with CMS
Section titled “Sign & Encrypt with CMS”# Sign a document (detached signature)qpki cms sign --data doc.pdf --cert signer.crt --key signer.key --out doc.p7s
# Verify signatureqpki cms verify doc.p7s --data doc.pdf --ca ca.crt
# Encrypt for recipient (supports ECDH, RSA, ML-KEM)qpki cms encrypt --recipient bob.crt --in secret.txt --out secret.p7m
# Decryptqpki cms decrypt --key bob.key --in secret.p7m --out secret.txtRevocation
Section titled “Revocation”# Revoke a certificate by serial numberqpki cert revoke 02 --ca-dir ./myca --reason superseded
# Revoke and generate new CRLqpki cert revoke 02 --ca-dir ./myca --gen-crl
# Generate/update CRLqpki crl gen --ca-dir ./myca --days 30Certificate Profiles
Section titled “Certificate Profiles”Profiles are YAML files that define how certificates are issued. 1 profile = 1 certificate type.
QPKI includes 50+ built-in profiles covering common use cases. All examples in this README use these built-in profiles for simplicity.
# List all built-in profilesqpki profile list
# View profile detailsqpki profile info hybrid/catalyst/tls-server
# Export a profile to customize itqpki profile export ec/tls-server ./my-tls-server.yaml
# Export all profiles for referenceqpki profile export --all ./templates/You can also create custom profiles from scratch. See Profiles for the full YAML specification.
Profile Categories:
| Category | Description |
|---|---|
ec/* | ECDSA profiles (modern classical) |
rsa/* | RSA profiles (legacy compatibility) |
ml/* | ML-DSA and ML-KEM (post-quantum) |
slh/* | SLH-DSA (hash-based post-quantum) |
hybrid/catalyst/* | Catalyst dual-key (ITU-T X.509 9.8) |
hybrid/composite/* | IETF composite signatures |
Example Profile (catalyst mode):
name: hybrid/catalyst/tls-servermode: catalystalgorithms: - ecdsa-p256 - ml-dsa-65validity: 365dextensions: keyUsage: values: [digitalSignature] extKeyUsage: values: [serverAuth]See Profiles for details.
Credentials
Section titled “Credentials”A credential is a managed bundle of private key(s) + certificate(s) with coupled lifecycle management (enrollment, renewal, revocation).
credential enroll generates everything in one command:
qpki credential enroll --ca-dir ./myca --profile ec/tls-client --var cn=Alice# → credentials/<id>/{credential.meta.json, certificates.pem, private-keys.pem}Why use credentials?
- Coupled lifecycle: Renew or revoke all certificates at once
- Multi-certificate: Use multiple
--profileflags for crypto-agility (classical + PQC)
# Create credential with multiple profiles (crypto-agility)qpki credential enroll --ca-dir ./myca --profile ec/client --profile ml/client --var cn=Alice
# Create credential with custom IDqpki credential enroll --ca-dir ./myca --profile hybrid/catalyst/tls-client --var cn=Alice --id alice-prodManage credential lifecycle:
# List credentialsqpki credential list
# Show credential detailsqpki credential info alice-20250115-abc123
# Renew all certificates in a credentialqpki credential rotate alice-20250115-abc123
# Renew with crypto migration (add/change profiles)qpki credential rotate alice-20250115-abc123 --profile ec/client --profile ml/client
# Revoke all certificates in a credentialqpki credential revoke alice-20250115-abc123 --reason keyCompromiseSee Credentials for details.
Interoperability & Compatibility
Section titled “Interoperability & Compatibility”This project focuses on real-world Post-Quantum PKI interoperability. All artifacts are designed to be compatible with standard PKI tooling and are cross-tested with external implementations.
Standards Compliance
Section titled “Standards Compliance”| Standard | Description | Status |
|---|---|---|
| RFC 5280 | X.509 Certificates and CRL | 🟢 |
| RFC 2986 | PKCS#10 CSR | 🟢 |
| RFC 9883 | ML-KEM CSR Attestation | 🟢 |
| RFC 6960 | OCSP | 🟢 |
| RFC 3161 | TSA Timestamping | 🟢 |
| RFC 5652 | CMS Signed Data | 🟢 |
| RFC 8419 | EdDSA in CMS | 🟢 |
| RFC 9814 | SLH-DSA in CMS | 🟢 |
| RFC 9882 | ML-DSA in CMS | 🟢 |
| FIPS 203 | ML-KEM | 🟢 |
| FIPS 204 | ML-DSA | 🟢 |
| FIPS 205 | SLH-DSA | 🟢 |
| ITU-T X.509 9.8 | Catalyst (dual-key extensions) | 🟢 |
| IETF draft-13 | Composite Signatures | 🟢 |
Interoperability Matrix
Section titled “Interoperability Matrix”Artifacts are validated using OpenSSL 3.6+ and BouncyCastle 1.83+.
Certificates
Section titled “Certificates”| Type | QPKI | OpenSSL | BouncyCastle |
|---|---|---|---|
| Classical (ECDSA/RSA) | 🟢 | 🟢 verify | 🟢 verify |
| PQC (ML-DSA, SLH-DSA) | 🟢 | 🟢 verify | 🟢 verify |
| Catalyst Hybrid | 🟢 both sigs | 🟢 ECDSA only | 🟢 both sigs |
| Composite (IETF) | 🟢 both sigs | 🔴 | 🟡 parse only* |
CSR (Certificate Signing Requests)
Section titled “CSR (Certificate Signing Requests)”| Type | QPKI | OpenSSL | BouncyCastle |
|---|---|---|---|
| Classical | 🟢 | 🟢 verify | 🟢 verify |
| PQC (ML-DSA) | 🟢 | 🟢 verify | 🟢 verify |
| ML-KEM (RFC 9883) | 🟢 | 🟢 parse | 🟢 verify |
| Hybrid | 🟢 | 🟢 primary | 🟢 both sigs |
CRL (Certificate Revocation Lists)
Section titled “CRL (Certificate Revocation Lists)”| Type | QPKI | OpenSSL | BouncyCastle |
|---|---|---|---|
| Classical | 🟢 | 🟢 verify | 🟢 verify |
| PQC (ML-DSA, SLH-DSA) | 🟢 | 🟢 verify | 🟢 verify |
| Catalyst Hybrid | 🟢 both sigs | 🟢 ECDSA only | 🟢 both sigs |
| Composite (IETF) | 🟢 both sigs | 🔴 | 🟡 parse only* |
OCSP, TSA, CMS
Section titled “OCSP, TSA, CMS”| Artifact | QPKI | OpenSSL | BouncyCastle |
|---|---|---|---|
| OCSP Response | 🟢 | 🟢 verify | 🟢 verify |
| TSA Timestamp | 🟢 | 🟢 verify | 🟢 verify |
| CMS Signed Data | 🟢 | 🟢 verify | 🟢 verify |
| CMS Enveloped (ML-KEM) | 🟢 | 🟢 decrypt | 🟢 decrypt |
Known Limitations
Section titled “Known Limitations”| Feature | Status | Notes |
|---|---|---|
| Composite signatures | 🟡 Partial | BC 1.83 uses draft-07 OIDs, we use IETF draft-13 |
| OpenSSL Catalyst | 🟡 Partial | Only ECDSA signature verified, PQC ignored |
| HSM support (PKCS#11) | 🟢 | Tested with SoftHSM; hardware HSM not yet validated |
*Composite: BC 1.83 implements draft-07 (Entrust OIDs 2.16.840.1.114027.80.8.1.x), our implementation uses draft-13 (IETF standard OIDs 1.3.6.1.5.5.7.6.x). Certificates parse correctly but signature verification requires OID migration in BC.
Running Cross-Tests
Section titled “Running Cross-Tests”make crosstest # All (OpenSSL + BouncyCastle)make crosstest-openssl # OpenSSL onlymake crosstest-bc # BouncyCastle only (requires Java 17+)OpenSSL and BouncyCastle are used for interoperability validation only. This project does not embed nor depend on these libraries.
See docs/dev/TESTING.md for details on the testing strategy.
Documentation
Section titled “Documentation”Getting Started
Section titled “Getting Started”| Document | Description |
|---|---|
| Installation | Download binaries, Homebrew, or build from source |
| Quick Start | Create your first CA and certificate in 5 minutes |
| Post-Quantum | PQC algorithms and hybrid certificates |
Core PKI
Section titled “Core PKI”| Document | Description |
|---|---|
| CA | CA initialization and management |
| Profiles | Certificate profile templates |
| Keys & CSR | Key generation and CSR operations |
| Certificates | Certificate issuance |
| CRL | Revocation lists |
End Entities
Section titled “End Entities”| Document | Description |
|---|---|
| Credentials | Bundled key + certificate lifecycle |
Services
Section titled “Services”| Document | Description |
|---|---|
| OCSP | Real-time certificate status (RFC 6960) |
| TSA | Timestamping service (RFC 3161) |
| CMS | CMS signatures and encryption (RFC 5652) |
| COSE | CBOR Object Signing (IoT, attestation) |
| SSH | SSH certificate issuance (OpenSSH format) |
Operations
Section titled “Operations”| Document | Description |
|---|---|
| HSM | Hardware Security Module integration (PKCS#11) |
| Audit | Audit logging and SIEM integration |
Migration
Section titled “Migration”| Document | Description |
|---|---|
| Crypto-Agility | Algorithm migration guide |
| Hybrid | Hybrid certificates |
Reference
Section titled “Reference”| Document | Description |
|---|---|
| CLI | Complete command reference |
| Troubleshooting | Common errors and solutions |
| Standards | OIDs and formats |
| PKI Basics | Certificates, keys, CAs, trust chains |
| Glossary | PKI and PQC terminology |
Development
Section titled “Development”| Document | Description |
|---|---|
| Architecture | System architecture overview |
| Contributing | Contribution guide |
| Testing | Testing guide |
| Interoperability | Interop testing |
Developed and maintained by Remi Blancher, cryptography and PKI specialist with 20+ years of experience in cryptographic infrastructures and post-quantum migration.
For questions, feedback, or professional inquiries:
- Email: remi.blancher@proton.me
- LinkedIn: linkedin.com/in/remiblancher
License
Section titled “License”Apache License 2.0 - See LICENSE for details.