# OpenSSL Configuration for Hybrid Root CA # Classical Path: ECDSA P-256 (universal compatibility, resource-efficient) # Post-Quantum Path: ML-DSA-87/Dilithium5 (quantum-resistant, future-proof) [ req ] default_days = 7300 default_md = sha256 distinguished_name = req_distinguished_name x509_extensions = v3_ca string_mask = utf8only prompt = no [ req_distinguished_name ] CN = Hybrid Root CA [ v3_ca ] # Basic constraints - critical for CA certificates basicConstraints = critical, CA:TRUE keyUsage = critical, digitalSignature, keyCertSign, cRLSign # Subject Key Identifier subjectKeyIdentifier = hash # Certificate policies (optional) certificatePolicies = @ca_policies [ ca_policies ] policyIdentifier = 2.5.29.32.0 # wildcard issue all. # CPS.1 = "https://example.com/cps" # ============================================================================= # HYBRID CERTIFICATE STRATEGY # ============================================================================= # # Your approach is excellent! By using ECDSA P-256 for both IoT and browsers, # you get universal compatibility while the ML-DSA-87 root provides quantum # resistance for future-ready intermediate certificates. # # DEPLOYMENT MODEL: # # 1. ECDSA P-256 Root CA → Issues intermediates for current use # ├─ IoT Intermediate CA → Issues device certificates # └─ VPS Intermediate CA → Issues server certificates (browser-compatible) # # 2. ML-DSA-87 Root CA → Issues quantum-safe intermediates # ├─ PQ IoT Intermediate CA → For future IoT with PQ support # └─ PQ VPS Intermediate CA → For browsers when ML-DSA support arrives # # BENEFITS: # - Single ECDSA key serves all current needs efficiently # - ML-DSA root is ready when ecosystem supports it # - Intermediate certificates can be cross-signed by both roots # - No redundant security overlap between the two paths # - Clear migration path as PQ support becomes available # # ============================================================================= # GENERATION COMMANDS # ============================================================================= # # 1. CLASSICAL PATH: ECDSA P-256 ROOT CA # # Generate P-256 private key: # openssl ecparam -name prime256v1 -genkey -noout -out root-ca-p256.key # # Protect the private key (highly recommended): # chmod 400 root-ca-p256.key # # Create self-signed root certificate: # openssl req -new -x509 -days 7300 -sha256 -config root-ca.cnf \ # -key root-ca-p256.key -out root-ca-p256.crt # # Verify the certificate: # openssl x509 -in root-ca-p256.crt -text -noout # # Extract public key (for verification): # openssl x509 -in root-ca-p256.crt -pubkey -noout > root-ca-p256.pub # # # 2. POST-QUANTUM PATH: ML-DSA-87 ROOT CA # # Prerequisites: # - OpenSSL 3.2+ with OQS provider # - Install: https://github.com/open-quantum-safe/oqs-provider # # Install OQS provider (Ubuntu/Debian): # sudo apt update # sudo apt install cmake ninja-build # git clone https://github.com/open-quantum-safe/liboqs.git # cd liboqs && mkdir build && cd build # cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local .. # ninja && sudo ninja install # # cd ../.. # git clone https://github.com/open-quantum-safe/oqs-provider.git # cd oqs-provider && mkdir build && cd build # cmake -GNinja -DCMAKE_INSTALL_PREFIX=/usr/local .. # ninja && sudo ninja install # # Generate ML-DSA-87 (Dilithium5) private key: # openssl genpkey -algorithm mldsa87 -out root-ca-mldsa87.key # # Protect the private key: # chmod 400 root-ca-mldsa87.key # # Create self-signed root certificate: # openssl req -new -x509 -days 7300 -sha256 -config root-ca.cnf \ # -key root-ca-mldsa87.key -out root-ca-mldsa87.crt # # Verify the certificate: # openssl x509 -in root-ca-mldsa87.crt -text -noout # # Extract public key: # openssl x509 -in root-ca-mldsa87.crt -pubkey -noout > root-ca-mldsa87.pub # # # 3. VERIFY BOTH ROOTS # # Check P-256 certificate details: # openssl x509 -in root-ca-p256.crt -text -noout | grep -A3 "Public Key" # # Should show: Public Key Algorithm: id-ecPublicKey # # Public-Key: (256 bit) # # Check ML-DSA-87 certificate details: # openssl x509 -in root-ca-mldsa87.crt -text -noout | grep -A3 "Public Key" # # Should show: Public Key Algorithm: ML-DSA-87 # # Verify certificate validity periods: # openssl x509 -in root-ca-p256.crt -noout -dates # openssl x509 -in root-ca-mldsa87.crt -noout -dates # # ============================================================================= # ISSUING INTERMEDIATE CERTIFICATES # ============================================================================= # # You'll need to create intermediate CA configurations and sign them with # both roots. Here's the workflow: # # 1. Create intermediate CA private key (P-256 for compatibility): # openssl ecparam -name prime256v1 -genkey -noout \ # -out intermediate-ca.key # # 2. Create intermediate CSR: # openssl req -new -key intermediate-ca.key \ # -out intermediate-ca.csr -config intermediate-ca.cnf # # 3. Sign with P-256 root (for current use): # openssl x509 -req -in intermediate-ca.csr -days 3650 \ # -CA root-ca-p256.crt -CAkey root-ca-p256.key \ # -CAcreateserial -out intermediate-ca-p256-signed.crt \ # -extfile intermediate-ca.cnf -extensions v3_intermediate_ca # # 4. Sign with ML-DSA-87 root (for future PQ use): # openssl x509 -req -in intermediate-ca.csr -days 3650 \ # -CA root-ca-mldsa87.crt -CAkey root-ca-mldsa87.key \ # -CAcreateserial -out intermediate-ca-mldsa87-signed.crt \ # -extfile intermediate-ca.cnf -extensions v3_intermediate_ca # # Now you have the same intermediate CA signed by both roots! # # ============================================================================= # COMPARISON: ECDSA P-256 vs ML-DSA-87 # ============================================================================= # # Property | ECDSA P-256 | ML-DSA-87 (Dilithium5) # ----------------------|----------------|------------------------ # Security Level | 128-bit | 256-bit (NIST Level 5) # Quantum Resistant | NO | YES # Key Size | 256 bits | 4656 bits # Public Key Size | ~64 bytes | ~2592 bytes # Signature Size | ~64 bytes | ~4595 bytes # Certificate Size | ~600 bytes | ~5 KB # Sign Time | ~0.5ms | ~2ms # Verify Time | ~0.3ms | ~1.5ms # Browser Support | Universal | Not yet (planned 2028-2030) # IoT Compatibility | Excellent | Limited (high memory) # TLS 1.3 Support | Yes | Yes (with OQS provider) # OpenSSL Version | 1.0.1+ | 3.2+ with OQS # # ============================================================================= # SECURITY CONSIDERATIONS # ============================================================================= # # ECDSA P-256 Root: # - Provides 128-bit classical security (equivalent to RSA-3072) # - Vulnerable to Shor's algorithm on quantum computers # - Expected to remain secure until ~2030-2035 (optimistic estimates) # - NIST-approved curve (FIPS 186-4) # - No known classical attacks that reduce security # # ML-DSA-87 Root: # - Provides NIST security level 5 (highest available) # - Resistant to both classical and quantum attacks # - Based on lattice cryptography (module lattices) # - NIST-standardized as FIPS 204 (August 2024) # - Conservative parameter set (Dilithium5 → ML-DSA-87) # # Hash Algorithm: # - SHA-256 is sufficient for P-256 (matching security levels) # - SHA-256 also works for ML-DSA-87 (ML-DSA has internal security) # # Key Storage: # - CRITICAL: Store both root private keys in HSM or offline storage # - Never expose root private keys to internet-connected systems # - Use intermediate CAs for day-to-day certificate issuance # - Consider geographic separation of P-256 and ML-DSA-87 keys # - Implement key ceremony procedures for root key access # # Certificate Validity: # - 20 years (7300 days) for root CAs is industry standard # - Intermediate CAs: 10 years maximum # - End-entity certificates: 1 year (current browser requirements) # # ============================================================================= # DEPLOYMENT TIMELINE # ============================================================================= # # Phase 1 (2026-2027): Current State # - Deploy ECDSA P-256 root for all production use # - Issue intermediate CAs for IoT and VPS services # - Store ML-DSA-87 root securely offline # - Monitor browser/client PQ support development # # Phase 2 (2028-2029): Hybrid Transition # - Begin issuing dual-signed intermediates (P-256 + ML-DSA-87) # - Test ML-DSA-87 certificates with compatible clients # - Gradually enable PQ support for VPS services # - Keep P-256 chain active for legacy compatibility # # Phase 3 (2030+): Post-Quantum Migration # - Primary use of ML-DSA-87 intermediates for new certificates # - P-256 chain remains for legacy IoT devices that cannot update # - Full PQ protection for all VPS and modern IoT traffic # - Consider rotating ML-DSA-87 root if cryptanalysis advances # # ============================================================================= # TROUBLESHOOTING # ============================================================================= # # If ML-DSA-87 generation fails: # 1. Verify OQS provider installation: # openssl list -providers # # Should show "oqsprovider" in the list # # 2. Check available PQ algorithms: # openssl list -signature-algorithms -provider oqsprovider # # Should show mldsa44, mldsa65, mldsa87 # # 3. Test OQS provider: # openssl genpkey -algorithm mldsa87 -provider oqsprovider \ # -out test.key && echo "Success!" || echo "Failed" # # 4. Check OpenSSL version: # openssl version # # Must be 3.2 or higher # # If intermediate signing fails: # - Ensure intermediate config has proper v3_intermediate_ca extensions # - Verify pathlen constraints allow intermediate issuance # - Check that CA:TRUE is set in the intermediate certificate # # =============================================================================