← Back to Research
Overview
Transition path to post-quantum cryptography before quantum computers break current email encryption (DKIM, TLS, S/MIME, PGP).
Problem Statement
Quantum computers threaten email security: - RSA: Broken by Shor's algorithm (factoring) - ECC: Broken by quantum algorithms - Current email crypto: All vulnerable (DKIM, TLS, S/MIME, PGP)
Timeline: NIST predicts quantum threat by 2030-2035
"Harvest now, decrypt later" attack: Adversaries recording encrypted email today to decrypt with future quantum computers
Vision
Quantum-Resistant Email
Replace vulnerable crypto:
❌ RSA-2048 → ✅ Kyber (lattice-based)
❌ ECDSA → ✅ Dilithium (signatures)
❌ ECDH → ✅ Kyber (key exchange)
Hybrid approach during transition:
- Classical + Post-quantum (defense in depth)
- Backward compatible
- Future-proof
NIST Post-Quantum Standards
Selected Algorithms (2024)
- Kyber (CRYSTALS-Kyber) - Key encapsulation
- Dilithium (CRYSTALS-Dilithium) - Digital signatures
- Falcon - Digital signatures (compact)
- SPHINCS+ - Stateless hash-based signatures
Use Cases in Email
TLS 1.3 (transport):
- Kyber for key exchange
- Dilithium for certificate signatures
DKIM (message signing):
- Dilithium for message signatures
S/MIME/PGP (end-to-end):
- Kyber for encryption
- Dilithium for signatures
Hybrid Cryptography (Transition Strategy)
Why Hybrid?
- Conservative: If PQC breaks, classical crypto still protects
- Compatible: Gradual rollout
- Future-proof: Both must break for failure
Example: Hybrid TLS
Classical TLS 1.3:
Client → [ECDH key exchange] → Server
Hybrid TLS:
Client → [ECDH + Kyber key exchange] → Server
Shared secret = KDF(ECDH_secret || Kyber_secret)
Both must be broken to decrypt
Technical Implementation
1. Quantum-Safe DKIM
Traditional DKIM:
DKIM-Signature: v=1; a=rsa-sha256; d=msgs.global;
s=default; h=from:to:subject:date;
bh=base64-body-hash;
b=base64-rsa-signature
Quantum-Safe DKIM (Hybrid):
DKIM-Signature: v=2; a=rsa-sha256+dilithium3; d=msgs.global;
s=default; h=from:to:subject:date;
bh=base64-body-hash;
b=base64-rsa-signature;
b-pq=base64-dilithium-signature
DNS TXT record:
_default._domainkey.msgs.global IN TXT (
"v=DKIM2; k=rsa+dilithium3; "
"p=base64-rsa-pubkey; "
"p-pq=base64-dilithium-pubkey;"
)
Verification:
def verify_hybrid_dkim(message):
"""Verify both classical and PQ signatures"""
# Extract signatures
rsa_sig = message.headers['DKIM-Signature']['b']
dilithium_sig = message.headers['DKIM-Signature']['b-pq']
# Fetch public keys from DNS
keys = fetch_dkim_keys(message.domain, message.selector)
# Verify both
rsa_valid = verify_rsa(message, keys['rsa'], rsa_sig)
dilithium_valid = verify_dilithium(message, keys['dilithium'], dilithium_sig)
# Both must pass for hybrid validation
return rsa_valid and dilithium_valid
2. Quantum-Safe TLS (Transport Layer)
OpenSSL 3.x with OQS Provider:
# Install liboqs (Open Quantum Safe)
git clone https://github.com/open-quantum-safe/liboqs.git
cd liboqs && mkdir build && cd build
cmake -DCMAKE_INSTALL_PREFIX=/usr/local ..
make && make install
# Install OQS-OpenSSL
git clone https://github.com/open-quantum-safe/openssl.git
cd openssl
./config --prefix=/usr/local/ssl
make && make install
Postfix Configuration:
# /etc/postfix/main.cf
# Enable quantum-safe TLS
smtpd_tls_security_level = may
smtpd_tls_protocols = TLSv1.3
tls_preempt_cipherlist = yes
# Hybrid ciphersuites (classical + PQ)
smtpd_tls_mandatory_ciphers = high
smtpd_tls_ciphers = TLS_AES_256_GCM_SHA384:KYBER768_AES_256_GCM_SHA384
# Certificate with hybrid signature
smtpd_tls_cert_file = /etc/ssl/certs/msgs.global-hybrid.pem
smtpd_tls_key_file = /etc/ssl/private/msgs.global-hybrid.key
3. Quantum-Safe End-to-End (S/MIME Alternative)
PQC-Mail Protocol:
class QuantumSafeMailEncryption:
"""Hybrid classical + PQ encryption"""
def __init__(self):
# Classical keypair (RSA)
self.rsa_key = RSA.generate(2048)
# PQ keypair (Kyber)
self.kyber_key = oqs.KeyEncapsulation('Kyber768')
def encrypt_message(self, message, recipient_public_keys):
"""Hybrid encryption"""
# 1. Generate random symmetric key
symmetric_key = os.urandom(32) # AES-256 key
# 2. Encrypt message with symmetric key
encrypted_message = AES_GCM.encrypt(message, symmetric_key)
# 3. Encrypt symmetric key with BOTH classical and PQ
# Classical: RSA-OAEP
rsa_encrypted_key = recipient_public_keys['rsa'].encrypt(
symmetric_key,
padding.OAEP(mgf=padding.MGF1(hashes.SHA256()), ...)
)
# PQ: Kyber encapsulation
kyber_ciphertext, kyber_shared_secret = recipient_public_keys['kyber'].encap_secret()
# Combine both secrets
combined_key = KDF(rsa_encrypted_key || kyber_shared_secret)
# Re-encrypt symmetric key with combined key
final_encrypted_key = AES_GCM.encrypt(symmetric_key, combined_key)
return {
'encrypted_message': encrypted_message,
'encrypted_key': final_encrypted_key,
'rsa_component': rsa_encrypted_key,
'kyber_component': kyber_ciphertext
}
def decrypt_message(self, encrypted_data, private_keys):
"""Hybrid decryption"""
# 1. Decrypt with RSA
rsa_key = private_keys['rsa'].decrypt(
encrypted_data['rsa_component'],
padding.OAEP(...)
)
# 2. Decrypt with Kyber
kyber_shared_secret = private_keys['kyber'].decap_secret(
encrypted_data['kyber_component']
)
# 3. Combine
combined_key = KDF(rsa_key || kyber_shared_secret)
# 4. Decrypt final symmetric key
symmetric_key = AES_GCM.decrypt(
encrypted_data['encrypted_key'],
combined_key
)
# 5. Decrypt message
message = AES_GCM.decrypt(
encrypted_data['encrypted_message'],
symmetric_key
)
return message
4. Key Management
Database Schema:
-- PQ keys for users
CREATE TABLE pq_keys (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
algorithm VARCHAR(50), -- Kyber768, Dilithium3, etc.
key_type VARCHAR(20), -- encryption, signing
public_key BYTEA,
private_key BYTEA, -- Encrypted at rest
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP
);
-- Hybrid key bundles
CREATE TABLE hybrid_key_bundles (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id),
classical_key_id INTEGER, -- References traditional keys
pq_key_id INTEGER REFERENCES pq_keys(id),
active BOOLEAN DEFAULT TRUE
);
API:
@app.route('/api/v1/pq/keys/generate', methods=['POST'])
def generate_pq_keys():
"""Generate quantum-safe keypair"""
user = request.current_user
# Generate Kyber keypair (encryption)
kyber = oqs.KeyEncapsulation('Kyber768')
kyber_public, kyber_secret = kyber.generate_keypair()
# Generate Dilithium keypair (signing)
dilithium = oqs.Signature('Dilithium3')
dilithium_public, dilithium_secret = dilithium.generate_keypair()
# Store keys
kyber_key = PQKey(
user_id=user.id,
algorithm='Kyber768',
key_type='encryption',
public_key=kyber_public,
private_key=encrypt_private_key(kyber_secret) # Encrypt before storage
)
dilithium_key = PQKey(
user_id=user.id,
algorithm='Dilithium3',
key_type='signing',
public_key=dilithium_public,
private_key=encrypt_private_key(dilithium_secret)
)
db.session.add_all([kyber_key, dilithium_key])
db.session.commit()
return jsonify({
'encryption_key_id': kyber_key.id,
'signing_key_id': dilithium_key.id,
'public_keys': {
'encryption': base64.b64encode(kyber_public).decode(),
'signing': base64.b64encode(dilithium_public).decode()
}
})
Migration Timeline
Phase 1: Research & Testing (2026)
- [x] Research NIST PQC algorithms
- [ ] Benchmark performance (Kyber, Dilithium)
- [ ] Build prototype hybrid TLS
- [ ] Test interoperability
Phase 2: Hybrid Deployment (2027)
- [ ] Deploy hybrid DKIM signatures
- [ ] Enable hybrid TLS on relay servers
- [ ] Generate PQ keys for users (opt-in)
- [ ] Update webmail to support PQ encryption
Phase 3: Transition (2028-2030)
- [ ] Make PQ default (hybrid still supported)
- [ ] Migrate all DKIM keys to hybrid
- [ ] Require PQ for sensitive communications
Phase 4: PQ-Only (2031+)
- [ ] Deprecate classical-only crypto
- [ ] Full quantum-safe deployment
Performance Impact
Key Sizes
| Algorithm | Public Key | Signature | Performance |
|---|---|---|---|
| RSA-2048 | 256 bytes | 256 bytes | Baseline |
| Dilithium3 | 1,952 bytes | 3,293 bytes | 3x CPU |
| Kyber768 | 1,184 bytes | - | 5x faster than RSA |
DNS Record Size
Traditional DKIM: ~300 bytes
Hybrid DKIM: ~2,500 bytes (fits in DNS)
TLS Handshake
Classical TLS 1.3: ~4 KB
Hybrid TLS (ECDH+Kyber): ~6 KB (+50%)
Latency impact: +5-10ms
Testing & Validation
Compatibility Testing
def test_hybrid_dkim():
"""Test hybrid DKIM signature"""
message = create_test_message()
# Sign with hybrid algorithm
signature = sign_hybrid_dkim(message)
# Verify classical component
assert verify_rsa_dkim(message, signature)
# Verify PQ component
assert verify_dilithium_dkim(message, signature)
# Test backward compatibility (legacy verifiers)
assert legacy_verify_dkim(message, signature) # Should pass RSA-only
Performance Benchmarks
# Benchmark signing/verification
python benchmark_pq_dkim.py
> RSA-2048 signing: 0.5ms
> Dilithium3 signing: 1.2ms
> RSA verification: 0.1ms
> Dilithium3 verification: 0.8ms
> Hybrid total: 2.6ms (acceptable for email)
Advantages
- Future-proof: Resistant to quantum attacks
- Hybrid security: Both classical and PQ must break
- Gradual migration: No flag day
- Standardized: NIST-approved algorithms
- Backward compatible: Legacy systems still work
Related Standards
- NIST SP 800-208: Post-Quantum Cryptography
- IETF Hybrid Key Exchange in TLS 1.3
- IETF PQ in X.509 Certificates
- OQS (Open Quantum Safe) Project
Status
📋 Research Phase (Standards Emerging)
Next Steps
- [ ] Install liboqs and test PQ algorithms
- [ ] Prototype hybrid DKIM implementation
- [ ] Benchmark performance on production hardware
- [ ] Design migration plan for existing keys
- [ ] Test backward compatibility
- [ ] Monitor IETF standardization efforts
- [ ] Plan gradual rollout (test users → production)