← 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)

  1. Kyber (CRYSTALS-Kyber) - Key encapsulation
  2. Dilithium (CRYSTALS-Dilithium) - Digital signatures
  3. Falcon - Digital signatures (compact)
  4. 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

  1. Future-proof: Resistant to quantum attacks
  2. Hybrid security: Both classical and PQ must break
  3. Gradual migration: No flag day
  4. Standardized: NIST-approved algorithms
  5. 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

  1. [ ] Install liboqs and test PQ algorithms
  2. [ ] Prototype hybrid DKIM implementation
  3. [ ] Benchmark performance on production hardware
  4. [ ] Design migration plan for existing keys
  5. [ ] Test backward compatibility
  6. [ ] Monitor IETF standardization efforts
  7. [ ] Plan gradual rollout (test users → production)