Lab-09: PQC Encryption
Lab-09: PQC Encryption
Section titled “Lab-09: PQC Encryption”Post-Quantum Document Encryption with ML-KEM + CSR Attestation
Section titled “Post-Quantum Document Encryption with ML-KEM + CSR Attestation”Key Message: KEM keys can’t sign their own CSR. Enrollment evolves — attestation bridges signing and encryption identities.
The Scenario
Section titled “The Scenario”“We need to send confidential documents to partners. But wait — how do we prove someone owns an encryption key if that key can’t sign anything?”
This is the attestation problem. Unlike signing keys (ML-DSA), encryption keys (ML-KEM) can only encapsulate and decapsulate — they cannot create signatures. So the traditional CSR workflow breaks.
Document encryption is essential for:
- Confidential emails (S/MIME)
- HR documents (salaries, evaluations)
- Medical records (patient data)
- Legal contracts (pre-signature)
- Encrypted backups (offline protection)
Classical encryption (RSA, ECDH) will be broken by quantum computers. We need quantum-safe encryption today for documents that must remain confidential for years.
The KEM Key Problem (RFC 9883)
Section titled “The KEM Key Problem (RFC 9883)”Traditional CSR workflow:
- Generate key pair
- Create CSR and sign it with the private key
- CA verifies signature = proof of possession
┌──────────────────────────────────────────────────────────────────┐│ ││ THE PROBLEM WITH KEM KEYS ││ ││ ML-KEM keys can only: ││ ✓ Encapsulate (encrypt a shared secret) ││ ✓ Decapsulate (decrypt a shared secret) ││ ││ ML-KEM keys CANNOT: ││ ✗ Sign data ││ ✗ Create digital signatures ││ ✗ Prove possession via CSR signature! ││ ││ Solution: Use a SIGNING certificate to attest for the KEM key ││ │└──────────────────────────────────────────────────────────────────┘The Solution: CSR Attestation (RFC 9883)
Section titled “The Solution: CSR Attestation (RFC 9883)”┌──────────────────────────────────────────────────────────────────┐│ ││ CSR ATTESTATION WORKFLOW ││ ││ Step 1: Alice gets SIGNING certificate (ML-DSA-65) ││ ││ Step 2: Alice generates ML-KEM key pair locally ││ ││ Step 3: Alice creates CSR for encryption key ││ → CSR is signed by her SIGNING key (attestation) ││ ││ Step 4: CA verifies: ││ → CSR signature is valid ││ → Signing certificate is trusted ││ → Issues encryption cert with RelatedCertificate ││ ││ Result: Alice has TWO linked certificates ││ → Signing: ML-DSA-65 (for authentication) ││ → Encryption: ML-KEM-768 (for key encapsulation) ││ │└──────────────────────────────────────────────────────────────────┘What We’ll Do
Section titled “What We’ll Do”- Create Encryption CA
- Issue signing certificate (ML-DSA) 2b. Generate encryption CSR with attestation (ML-KEM) 2c. Issue encryption certificate
- Encrypt a document 3b. Decrypt the document
Run the Demo
Section titled “Run the Demo”./journey/09-cms-encryption/demo.shThe Commands
Section titled “The Commands”Step 1: Create Encryption CA
Section titled “Step 1: Create Encryption CA”qpki ca init --profile profiles/pqc-ca.yaml \ --var cn="Encryption CA" \ --ca-dir output/encryption-caStep 2: Issue Signing Certificate (ML-DSA-65)
Section titled “Step 2: Issue Signing Certificate (ML-DSA-65)”# Generate ML-DSA-65 key pair and CSR (self-signed = proof of possession)qpki csr gen --algorithm ml-dsa-65 \ --keyout output/alice-sign.key \ --cn "Alice" \ --out output/alice-sign.csr
qpki cert issue --ca-dir output/encryption-ca \ --profile profiles/pqc-signing.yaml \ --csr output/alice-sign.csr \ --out output/alice-sign.crtStep 2b: Generate Encryption Key and CSR (ML-KEM-768)
Section titled “Step 2b: Generate Encryption Key and CSR (ML-KEM-768)”# RFC 9883: KEM keys cannot sign, so signing cert "attests" ownership# --attest-cert: signing certificate that vouches for this KEM key# --attest-key: proves possession of the signing keyqpki csr gen --algorithm ml-kem-768 \ --keyout output/alice-enc.key \ --cn "Alice" \ --attest-cert output/alice-sign.crt \ --attest-key output/alice-sign.key \ --out output/alice-enc.csrStep 2c: Issue Encryption Certificate (ML-KEM-768)
Section titled “Step 2c: Issue Encryption Certificate (ML-KEM-768)”# CA verifies attestation and issues certificateqpki cert issue --ca-dir output/encryption-ca \ --csr output/alice-enc.csr \ --profile profiles/pqc-encryption.yaml \ --attest-cert output/alice-sign.crt \ --out output/alice-enc.crtStep 5 (Show Certificate Pair) is displayed in the demo but has no command.
Step 3: Encrypt Document (CMS EnvelopedData)
Section titled “Step 3: Encrypt Document (CMS EnvelopedData)”# Hybrid encryption: AES-256-GCM (fast, symmetric) + ML-KEM (quantum-safe key exchange)# ML-KEM encapsulates a shared secret → derives AES key → encrypts contentqpki cms encrypt \ --recipient output/alice-enc.crt \ --content-enc aes-256-gcm \ --in output/secret-document.txt \ --out output/secret-document.p7mStep 3b: Decrypt Document
Section titled “Step 3b: Decrypt Document”# Alice decrypts using her ML-KEM private keyqpki cms decrypt \ --key output/alice-enc.key \ --in output/secret-document.p7m \ --out output/decrypted.txtAlice’s Certificate Pair
Section titled “Alice’s Certificate Pair”┌─────────────────────────────────────────────────────────────────────┐│ ALICE'S CERTIFICATE PAIR │├─────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────┐ ┌─────────────────────────────┐ ││ │ SIGNING CERTIFICATE │ │ ENCRYPTION CERTIFICATE │ ││ ├─────────────────────────────┤ ├─────────────────────────────┤ ││ │ Algorithm: ML-DSA-65 │ │ Algorithm: ML-KEM-768 │ ││ │ Key Usage: digitalSignature│ │ Key Usage: keyEncipherment │ ││ │ File: alice-sign.crt │ │ File: alice-enc.crt │ ││ │ Purpose: Sign, Attest │ │ Purpose: Receive encrypted │ ││ └─────────────────────────────┘ └─────────────────────────────┘ ││ │ ▲ ││ │ RelatedCertificate │ ││ └──────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────┘CMS EnvelopedData Structure
Section titled “CMS EnvelopedData Structure”┌─────────────────────────────────────────────────────────────────────┐│ CMS EnvelopedData (RFC 5652) │├─────────────────────────────────────────────────────────────────────┤│ ││ ┌───────────────────────────────────────────────────────────────┐ ││ │ KEMRecipientInfo (for ML-KEM) │ ││ ├───────────────────────────────────────────────────────────────┤ ││ │ • Recipient ID (issuer + serial) │ ││ │ • KEM Algorithm: ML-KEM-768 │ ││ │ • KEM Ciphertext: ~1,088 bytes │ ││ │ • KDF: HKDF-SHA256 │ ││ │ • Key Wrap: AES-256-WRAP │ ││ │ • Wrapped Key: 40 bytes │ ││ └───────────────────────────────────────────────────────────────┘ ││ ││ ┌───────────────────────────────────────────────────────────────┐ ││ │ EncryptedContentInfo │ ││ ├───────────────────────────────────────────────────────────────┤ ││ │ • Content Type: id-data │ ││ │ • Algorithm: AES-256-GCM │ ││ │ • Encrypted Content: [ciphertext + GCM tag] │ ││ └───────────────────────────────────────────────────────────────┘ ││ │└─────────────────────────────────────────────────────────────────────┘Why Hybrid Encryption?
Section titled “Why Hybrid Encryption?”| Approach | Speed | Ciphertext Size | Quantum-Safe | Verdict |
|---|---|---|---|---|
| ML-KEM only | Slow | Large | Yes | Not practical for large files |
| AES only | Fast | Small | Yes* | Can’t share key securely |
| AES + ML-KEM | Fast | Small + ~1KB | Yes | Best of both worlds |
*AES is quantum-resistant but requires secure key exchange.
Use Cases
Section titled “Use Cases”| Scenario | Application | Why PQC? |
|---|---|---|
| Secure Email | S/MIME (Outlook, Thunderbird) | Emails may be archived for years |
| HR Documents | Salaries, performance reviews | Employee data is sensitive |
| Medical Records | HIPAA compliance | 50+ year retention requirements |
| Legal Contracts | Pre-signature confidentiality | Business secrets |
| Encrypted Backups | Offline archives | Long-term protection |
Algorithm Details
Section titled “Algorithm Details”ML-DSA-65 (Signing)
Section titled “ML-DSA-65 (Signing)”| Property | Value |
|---|---|
| NIST Standard | FIPS 204 |
| Security Level | NIST Level 3 (~192-bit classical) |
| Public Key | ~1,952 bytes |
| Signature | ~3,309 bytes |
| Purpose | CSR attestation, message signing |
ML-KEM-768 (Key Encapsulation)
Section titled “ML-KEM-768 (Key Encapsulation)”| Property | Value |
|---|---|
| NIST Standard | FIPS 203 |
| Security Level | NIST Level 3 (~192-bit classical) |
| Public Key | 1,184 bytes |
| Ciphertext | 1,088 bytes |
| Shared Secret | 32 bytes |
AES-256-GCM (Content Encryption)
Section titled “AES-256-GCM (Content Encryption)”| Property | Value |
|---|---|
| Key Size | 256 bits |
| Mode | Galois/Counter Mode (GCM) |
| Authentication | Built-in (AEAD) |
| IV Size | 12 bytes |
| Tag Size | 16 bytes |
What You Learned
Section titled “What You Learned”- KEM keys cannot sign — Traditional CSR proof-of-possession doesn’t work
- Attestation solves this — A signing certificate vouches for the KEM key (RFC 9883)
- Two linked certificates — Signing (ML-DSA) + Encryption (ML-KEM) via RelatedCertificate
- Hybrid encryption — AES for speed + ML-KEM for quantum-safe key exchange
References
Section titled “References”- RFC 9883: Use of Post-Quantum KEM in CMS
- NIST FIPS 203: ML-KEM Standard
- NIST FIPS 204: ML-DSA Standard
- RFC 5652: Cryptographic Message Syntax (CMS)
- RFC 5751: S/MIME Version 3.2