Post-Quantum Algorithms Explained: CRYSTALS-Kyber, CRYSTALS-Dilithium & .NET Support

🔐 NIST Post-Quantum Standards — 2024

Post-Quantum Cryptography Explained

CRYSTALS-Kyber · CRYSTALS-Dilithium · SPHINCS+ · .NET Integration

3
NIST Standards
Finalized 2024
2048+
Key sizes (bits)
Kyber-512 / 768 / 1024
Q-Day
Threat horizon
Est. 2030–2040
ML-KEM
FIPS 203
Kyber standard

Introduction: Why Post-Quantum Cryptography?

Classical public-key algorithms — RSA, ECDH, ECDSA — rely on mathematical problems (integer factorization, discrete logarithm) that are computationally hard for classical computers but solvable in polynomial time by a sufficiently large quantum computer using Shor's algorithm. When quantum computers reach sufficient scale (sometimes called "Q-Day"), all asymmetric encryption and digital signatures based on these problems will be broken.

Post-Quantum Cryptography (PQC) refers to cryptographic algorithms believed to be secure against both classical and quantum computers. In August 2024, NIST finalized three post-quantum standards: FIPS 203 (ML-KEM / Kyber), FIPS 204 (ML-DSA / Dilithium), and FIPS 205 (SLH-DSA / SPHINCS+).

🔑 NIST PQC Finalized Algorithms at a Glance

Algorithm FIPS Type Math Basis Public Key Use Case
ML-KEM (Kyber-768)FIPS 203KEMModule-LWE1184 bytesKey Exchange / TLS
ML-DSA (Dilithium3)FIPS 204SignatureModule-LWE/SIS1952 bytesCode/Doc Signing
SLH-DSA (SPHINCS+)FIPS 205SignatureHash-based32–64 bytesLong-term signing
RSA-2048 (classical)KEM+SigInteger Factoring256 bytes❌ Quantum-vulnerable

CRYSTALS-Kyber (ML-KEM)

Kyber is a Key Encapsulation Mechanism (KEM) based on the hardness of the Module Learning With Errors (MLWE) problem. It does not encrypt data directly — instead, it establishes a shared secret between two parties, which is then used as a symmetric key (e.g., for AES). Kyber comes in three security levels:

  • Kyber-512 — AES-128 equivalent security (512-bit module dimension)
  • Kyber-768 — AES-192 equivalent, NIST recommended for most applications
  • Kyber-1024 — AES-256 equivalent, for highest security requirements
C# — CRYSTALS-Kyber Key Encapsulation (using BouncyCastle)
// Install: dotnet add package BouncyCastle.Cryptography
using Org.BouncyCastle.Pqc.Crypto.Crystals.Kyber;
using Org.BouncyCastle.Security;

// Key Generation (receiver side)
var random = new SecureRandom();
var keyGenParams = new KyberKeyGenerationParameters(random, KyberParameters.kyber768);
var keyGen = new KyberKeyPairGenerator();
keyGen.Init(keyGenParams);
var keyPair = keyGen.GenerateKeyPair();

var publicKey  = (KyberPublicKeyParameters)keyPair.Public;
var privateKey = (KyberPrivateKeyParameters)keyPair.Private;

// Encapsulation (sender side — generates ciphertext + shared secret)
var encapsulator = new KyberKemGenerator(random);
var secretWithEncapsulation = encapsulator.GenerateEncapsulated(publicKey);
byte[] ciphertext    = secretWithEncapsulation.GetEncapsulation();
byte[] sharedSecretA = secretWithEncapsulation.GetSecret(); // 32 bytes

// Decapsulation (receiver side)
var decapsulator = new KyberKemExtractor(privateKey);
byte[] sharedSecretB = decapsulator.ExtractSecret(ciphertext);

// Both parties now hold identical shared secrets
Console.WriteLine($"Match: {sharedSecretA.SequenceEqual(sharedSecretB)}"); // True

// Use sharedSecret as AES key for actual data encryption
using var aes = Aes.Create();
aes.Key = sharedSecretA; // 256-bit AES key

CRYSTALS-Dilithium (ML-DSA)

Dilithium is a digital signature scheme based on the hardness of Module-LWE and Module-SIS problems. It produces signatures that are much larger than RSA or ECDSA but are considered secure against quantum attacks. FIPS 204 specifies three parameter sets: ML-DSA-44, ML-DSA-65, and ML-DSA-87.

C# — CRYSTALS-Dilithium Digital Signatures
using Org.BouncyCastle.Pqc.Crypto.Crystals.Dilithium;
using Org.BouncyCastle.Security;

var random = new SecureRandom();

// Generate Dilithium3 key pair (ML-DSA-65 equivalent)
var keyGenParams = new DilithiumKeyGenerationParameters(
    random, DilithiumParameters.Dilithium3);
var keyGen = new DilithiumKeyPairGenerator();
keyGen.Init(keyGenParams);
var keyPair = keyGen.GenerateKeyPair();

byte[] message = System.Text.Encoding.UTF8.GetBytes("Sign this document");

// Sign
var signer = new DilithiumSigner();
signer.Init(true, keyPair.Private);
signer.BlockUpdate(message, 0, message.Length);
byte[] signature = signer.GenerateSignature();

// Signature size for Dilithium3: ~3,293 bytes (vs ~256 for ECDSA P-256)
Console.WriteLine($"Sig size: {signature.Length} bytes");

// Verify
var verifier = new DilithiumSigner();
verifier.Init(false, keyPair.Public);
verifier.BlockUpdate(message, 0, message.Length);
bool isValid = verifier.VerifySignature(signature);
Console.WriteLine($"Valid: {isValid}"); // True

📊 Key & Signature Size Comparison

RSA-2048 Public Key (256 B)classical — quantum-broken
Kyber-768 Public Key (1,184 B)4.6× larger than RSA-2048
Dilithium3 Public Key (1,952 B)7.6× larger than RSA-2048
ECDSA P-256 Signature (64 B)classical — quantum-broken
Dilithium3 Signature (3,293 B)51× larger than ECDSA

SPHINCS+ (SLH-DSA)

SPHINCS+ is a stateless hash-based signature scheme. Unlike lattice-based schemes (Kyber, Dilithium), SPHINCS+ relies only on the security of hash functions — making it conservative and extremely well-understood. Its main tradeoff is larger signature sizes (8–50 KB depending on parameter set) and slower signing, but it offers excellent security guarantees and doesn't require any new mathematical assumptions.

C# — SPHINCS+ Signatures
using Org.BouncyCastle.Pqc.Crypto.SphincsPlus;

var random = new SecureRandom();
var keyParams = new SphincsPlusKeyGenerationParameters(
    random, SphincsPlusParameters.sha2_128f); // fast variant

var keyGen = new SphincsPlusKeyPairGenerator();
keyGen.Init(keyParams);
var keyPair = keyGen.GenerateKeyPair();

byte[] data = System.Text.Encoding.UTF8.GetBytes("SPHINCS+ test document");

var signer = new SphincsPlusSigner();
signer.Init(true, keyPair.Private);
signer.BlockUpdate(data, 0, data.Length);
byte[] sig = signer.GenerateSignature();

Console.WriteLine($"SPHINCS+ sig size: {sig.Length} bytes"); // ~17,088 bytes for sha2_128f

.NET 9 Native PQC Support

Starting with .NET 9 (released Nov 2024), Microsoft added native post-quantum algorithm support in System.Security.Cryptography. ML-KEM (Kyber) is available without BouncyCastle as of .NET 9 Preview builds, with ML-DSA support planned for .NET 10.

C# — .NET 9 Native ML-KEM
// .NET 9+ — System.Security.Cryptography.MLKem
using System.Security.Cryptography;

// Generate key pair (ML-KEM-768)
using var kem = MLKem.GenerateKey(MLKemAlgorithm.MLKem768);
byte[] publicKeyBytes = kem.ExportPublicKey();

// Encapsulate (sender)
MLKem.TryDecapsulate(publicKeyBytes, out byte[] ciphertext, out byte[] sharedSecretEnc);

// Decapsulate (receiver)
byte[] sharedSecretDec = kem.Decapsulate(ciphertext);

// Hybrid TLS: combine with classical ECDH for defense-in-depth
// NIST recommends "hybrid" key exchange during transition period

🗺️ PQC Migration Roadmap

1
Inventory — Identify all uses of RSA/ECC in your codebase: TLS certs, JWT signing, code signing, encryption at rest
2
Hybrid Mode — Deploy hybrid key exchange (X25519+Kyber768 or P-256+Kyber768) in TLS to gain quantum resistance while maintaining classical compatibility
3
Signature Migration — Move code signing, document signing, and PKI to ML-DSA (Dilithium) or SLH-DSA (SPHINCS+)
4
Full PQC — Complete transition before Q-Day. NSA CNSA 2.0 mandates PQC for all national security systems by 2030–2035

When to Use Which Algorithm

Choosing between PQC algorithms depends on your specific use case:

  • Key Exchange / TLS: Use ML-KEM (Kyber-768). It's the most mature, fastest option for establishing shared secrets in TLS 1.3 handshakes.
  • Code/Document Signing: Use ML-DSA (Dilithium3). Good balance of signing speed, verification speed, and key/signature sizes.
  • Long-term Archival Signatures: Use SLH-DSA (SPHINCS+). The only hash-based option; relies on no lattice assumptions. Ideal when you need signatures to be verifiable for 30+ years.
  • Resource-constrained IoT: Kyber-512 or Dilithium2 for smaller footprint, though still significantly larger than ECDSA.

Summary

Post-quantum cryptography is no longer theoretical — NIST has finalized three algorithms and both BouncyCastle and .NET 9 provide production-ready implementations. The transition from classical cryptography to PQC is a multi-year effort, but the time to start planning is now: "harvest now, decrypt later" attacks are already occurring, meaning adversaries are storing encrypted traffic today to decrypt once quantum computers arrive.

Post a Comment

Previous Post Next Post