Skip to content
Post-Quantum Cryptography

Post-Quantum Cryptography

Since: cryptopp-modern 2026.3.0

Post-Quantum Cryptography (PQC) provides cryptographic algorithms designed to be secure against attacks by both classical and quantum computers. cryptopp-modern implements the NIST PQC standards from FIPS 203, 204, 205, and the stateful hash-based signatures from SP 800-208.

Why Post-Quantum Cryptography?

Quantum computers pose a significant threat to current cryptographic systems:

  • RSA, ECDSA, ECDH, Ed25519, X25519 - All vulnerable to Shor’s algorithm on a sufficiently powerful quantum computer
  • AES, SHA-3, BLAKE3 - Remain secure (Grover’s algorithm only halves effective security)

The “Harvest Now, Decrypt Later” Threat: Adversaries may be collecting encrypted data today, planning to decrypt it once quantum computers become available. Data with long-term confidentiality requirements (medical records, state secrets, financial data) should transition to PQC now.

Available Algorithms

Key Encapsulation (Key Exchange)

AlgorithmStandardSecurity BasisRecommended For
ML-KEMFIPS 203Module latticesPure post-quantum key exchange
X-WingIETF DraftHybrid (X25519 + ML-KEM)Defence in depth (default for new work)

Digital Signatures (Stateless)

AlgorithmStandardSecurity BasisRecommended For
ML-DSAFIPS 204Module latticesGeneral-purpose signatures
SLH-DSAFIPS 205Hash functionsConservative security (no lattice assumptions)

Digital Signatures (Stateful)

AlgorithmStandardSecurity BasisRecommended For
LMS/HSSSP 800-208Hash functionsBounded signing (firmware, code signing, certificates)

Stateful schemes require explicit state management. Each signature consumes a one-time index that must never be reused. See the LMS/HSS page and the Stateful Signing Integration Guide for details.


Quick Comparison

Key Encapsulation Mechanisms

PropertyML-KEM-768X-WingX25519 (classical)
Public Key1184 bytes1216 bytes32 bytes
Secret Key (seed)64 bytes32 bytes32 bytes*
Ciphertext1088 bytes1120 bytes32 bytes
Shared Secret32 bytes32 bytes32 bytes
Quantum SecureYesYesNo
Classical SecureYesYesYes
Security if lattices brokenNoYes (X25519 backup)N/A

*X25519 secret key is not a seed in the ML-KEM/X-Wing sense.

Digital Signatures

PropertyML-DSA-65SLH-DSA-SHA2-128fHSS L=2 H5/W8Ed25519 (classical)
Public Key1952 bytes32 bytes60 bytes32 bytes
Secret Key4032 bytes64 bytes48 bytes64 bytes
Signature3309 bytes17,088 bytes2,644 bytes64 bytes
Quantum SecureYesYesYesNo
Security BasisLatticesHash functionsHash functionsElliptic curves
StatefulNoNoYesNo
Signing SpeedFastSlowMediumVery Fast
Verification SpeedFastSlowMediumFast

Choosing the Right Algorithm

For a worked decision tree covering hybrid vs pure post-quantum key exchange and signature selection, see Post-Quantum Cryptography: Choosing an Algorithm.

In summary:

  • Key encapsulation: X-Wing is the recommended default; it stays secure if either X25519 or ML-KEM-768 is broken. Use ML-KEM directly for pure post-quantum environments where defence-in-depth is unwanted.
  • Stateless signatures: ML-DSA-65 covers the general case. Pick SLH-DSA when you want hash-only security and can accept larger signatures.
  • Stateful signatures: LMS/HSS for bounded signing volumes where you can manage signer state durably. See LMS/HSS and the Stateful Signing Guide.
  • Maximum security: ML-DSA-87 or SLH-DSA-256 variants.

Security Levels

NIST defines security levels based on the computational effort to break:

LevelComparable ToAlgorithms
1AES-128 work factorML-KEM-512, SLH-DSA-128*
2SHA-256 collisionML-DSA-44
3AES-192 work factorML-KEM-768, ML-DSA-65, SLH-DSA-192*
5AES-256 work factorML-KEM-1024, ML-DSA-87, SLH-DSA-256*

Recommendation: Level 3 (ML-KEM-768, ML-DSA-65) provides excellent security for most applications.


Quick Examples

Hybrid Key Exchange with X-Wing

#include <cryptopp/xwing.h>
#include <cryptopp/osrng.h>
#include <cryptopp/secblock.h>
#include <cryptopp/cryptlib.h>
#include <cryptopp/hkdf.h>
#include <cryptopp/sha3.h>

using namespace CryptoPP;

// Recipient generates key pair
AutoSeededRandomPool rng;
XWingDecapsulator recipient(rng);

// Extract public key to send to sender
SecByteBlock publicKey(recipient.GetKey().GetPublicKeySize());
recipient.GetKey().GetPublicKey(publicKey.begin());

// Sender encapsulates (creates shared secret + ciphertext)
XWingEncapsulator sender(publicKey.begin(), publicKey.size());
SecByteBlock ciphertext(sender.CiphertextLength());
SecByteBlock senderSecret(sender.SharedSecretLength());
sender.Encapsulate(rng, ciphertext.begin(), senderSecret.begin());

// Recipient decapsulates to get same shared secret
SecByteBlock recipientSecret(recipient.SharedSecretLength());
bool success = recipient.Decapsulate(ciphertext.begin(), recipientSecret.begin());
if (!success) { throw Exception(Exception::OTHER_ERROR, "Decapsulation failed"); }

// Derive encryption key from shared secret using HKDF
HKDF<SHA3_256> hkdf;
SecByteBlock encryptionKey(32);
const byte info[] = "encryption";
hkdf.DeriveKey(encryptionKey.begin(), encryptionKey.size(),
               senderSecret.begin(), senderSecret.size(),
               nullptr, 0,  // salt (optional)
               info, sizeof(info) - 1);  // info

Post-Quantum Signatures with ML-DSA

#include <cryptopp/mldsa.h>
#include <cryptopp/osrng.h>
#include <cryptopp/secblock.h>
#include <string>

using namespace CryptoPP;

AutoSeededRandomPool rng;

// Generate key pair
MLDSASigner<MLDSA_65> signer(rng);
MLDSAVerifier<MLDSA_65> verifier(signer);

// Sign a message
std::string message = "Important document";
SecByteBlock signature(signer.SignatureLength());
size_t sigLen = signer.SignMessage(rng,
    (const byte*)message.data(), message.size(),
    signature.begin());

// Verify the signature
bool valid = verifier.VerifyMessage(
    (const byte*)message.data(), message.size(),
    signature.begin(), sigLen);

Migration Strategy

Phase 1: Hybrid Mode (Recommended Now)

Use hybrid algorithms that combine classical and post-quantum cryptography:

  • Key Exchange: X-Wing (X25519 + ML-KEM-768)
  • Signatures: Consider dual signatures (Ed25519 + ML-DSA) for critical applications

Benefits:

  • Secure against both classical and quantum attacks
  • If PQC algorithms have undiscovered weaknesses, classical algorithms provide backup
  • Gradual transition without breaking compatibility

Phase 2: Pure Post-Quantum (Future)

Once PQC algorithms are thoroughly analyzed and quantum computers become a near-term threat:

  • Key Exchange: ML-KEM-768 or ML-KEM-1024
  • Signatures: ML-DSA-65 or SLH-DSA

Timeline Considerations

ApplicationRecommended Action
Long-term secrets (25+ years)Migrate to hybrid PQC now
Financial/healthcare dataBegin hybrid migration
Real-time communicationsPlan for hybrid, classical still acceptable
Short-term sessionsClassical acceptable, plan for future

Indicative Performance

Key Generation

AlgorithmApproximate Time
X25519~40 µs
ML-KEM-768~100 µs
X-Wing~150 µs
ML-DSA-65~200 µs
SLH-DSA-SHA2-128f~5 ms
SLH-DSA-SHA2-128s~50 ms

Operations

OperationML-KEM-768X-WingML-DSA-65SLH-DSA-128f
Encaps/Sign~150 µs~200 µs~500 µs~100 ms
Decaps/Verify~100 µs~150 µs~200 µs~10 ms

Performance varies by platform and implementation; benchmark in your target environment.

Guidance:

  • ML-KEM and ML-DSA are fast enough for most applications
  • SLH-DSA is slower but provides hash-based security (no lattice assumptions)
  • X-Wing adds minimal overhead over pure ML-KEM

Thread Safety

PQC class instances are not thread-safe. Use one instance per thread:

// CORRECT: Per-thread instances
void signInThread(const MLDSAPrivateKey<MLDSA_65>& privateKey) {
    AutoSeededRandomPool rng;
    MLDSASigner<MLDSA_65> signer;
    signer.AccessPrivateKey().AssignFrom(privateKey);
    // ... sign ...
}

// INCORRECT: Shared instance
MLDSASigner<MLDSA_65> globalSigner;  // Don't do this

Algorithm Details

ML-KEM (FIPS 203)

Module-Lattice Key Encapsulation Mechanism. Successor to CRYSTALS-Kyber.

  • Three parameter sets: ML-KEM-512, ML-KEM-768, ML-KEM-1024
  • IND-CCA2 secure with implicit rejection
  • Recommended: ML-KEM-768 for most applications

ML-DSA (FIPS 204)

Module-Lattice Digital Signature Algorithm. Successor to CRYSTALS-Dilithium.

  • Three parameter sets: ML-DSA-44, ML-DSA-65, ML-DSA-87
  • EUF-CMA secure, probabilistic signing
  • Recommended: ML-DSA-65 for most applications

SLH-DSA (FIPS 205)

Stateless Hash-Based Digital Signature Algorithm. Successor to SPHINCS+.

  • 12 parameter sets (SHA2/SHAKE × 128/192/256 × fast/small)
  • Security based only on hash function properties
  • Recommended: SLH-DSA-SHA2-128f for speed, SLH-DSA-SHA2-128s for smaller signatures

X-Wing

Hybrid Key Encapsulation combining X25519 and ML-KEM-768.

  • Defence in depth: secure if either algorithm is secure
  • Proposed in IETF CFRG with active industry involvement (including Cloudflare)
  • Recommended: Default choice for new applications

Standards Compliance

AlgorithmStandardStatus
ML-KEMFIPS 203Final (13 August 2024)
ML-DSAFIPS 204Final (13 August 2024)
SLH-DSAFIPS 205Final (13 August 2024)
X-WingIETF DraftDraft

See Also