====== Parallel Operation ======
**Complexity:** Medium \\
**Duration:** Unlimited (until classic deactivated) \\
**Risk:** Low
Simultaneous operation of classic and post-quantum PKI for maximum compatibility.
----
===== Architecture =====
flowchart TB
subgraph CLASSIC["CLASSIC PKI"]
CR[Classic Root CA]
CI[Classic Intermediate]
CC[Classic Certificates]
end
subgraph HYBRID["HYBRID PKI"]
HR[Hybrid Root CA]
HI[Hybrid Intermediate]
HC[Hybrid Certificates]
end
subgraph CLIENTS["CLIENTS"]
OLD[Legacy Clients]
NEW[Modern Clients]
end
CR --> CI --> CC
HR --> HI --> HC
CC --> OLD
HC --> NEW
CC -.->|Fallback| NEW
style CLASSIC fill:#ffebee
style HYBRID fill:#e8f5e9
----
===== When Parallel Operation? =====
| Scenario | Recommendation |
|----------|----------------|
| Legacy systems not updatable | Parallel |
| Gradual migration over years | Parallel |
| Regulatory requirements for backward compatibility | Parallel |
| Greenfield / New project | Direct Hybrid |
| All clients updatable | Hybrid migration |
----
===== Setup =====
==== Directory Structure ====
/etc/pki/
+-- classic/
| +-- root-ca.pem
| +-- intermediate-ca.pem
| +-- intermediate-ca.key
| +-- crl/
| +-- issued/
+-- hybrid/
| +-- root-ca.pem
| +-- intermediate-ca.pem
| +-- intermediate-ca.key
| +-- crl/
| +-- issued/
+-- scripts/
+-- issue-classic.sh
+-- issue-hybrid.sh
+-- issue-both.sh
==== Dual-Issue Script ====
#!/bin/bash
# /etc/pki/scripts/issue-both.sh
# Issues a certificate from BOTH PKIs
CSR_FILE="$1"
OUTPUT_PREFIX="$2"
if [ -z "$CSR_FILE" ] || [ -z "$OUTPUT_PREFIX" ]; then
echo "Usage: $0 "
exit 1
fi
# Issue classic certificate
echo "Issuing classic certificate..."
openssl ca -config /etc/pki/classic/openssl.cnf \
-in "$CSR_FILE" \
-out "${OUTPUT_PREFIX}-classic.pem" \
-days 365 \
-batch
# Issue hybrid certificate
echo "Issuing hybrid certificate..."
/usr/local/bin/wvds-sign --mode hybrid \
--ca /etc/pki/hybrid/intermediate-ca.pfx \
--csr "$CSR_FILE" \
--out "${OUTPUT_PREFIX}-hybrid.pem" \
--days 365
echo "Done:"
echo " Classic: ${OUTPUT_PREFIX}-classic.pem"
echo " Hybrid: ${OUTPUT_PREFIX}-hybrid.pem"
----
===== Server Configuration =====
==== Nginx: Dual Certificate ====
server {
listen 443 ssl;
server_name api.example.com;
# Primary: Hybrid certificate
ssl_certificate /etc/ssl/certs/api-hybrid.pem;
ssl_certificate_key /etc/ssl/private/api.key;
# Fallback: Classic certificate (for old clients)
# Note: Nginx supports only one certificate per server block
# For true dual-mode: Separate server blocks or SNI
}
# Alternative: Separate server for legacy
server {
listen 443 ssl;
server_name api-legacy.example.com;
ssl_certificate /etc/ssl/certs/api-classic.pem;
ssl_certificate_key /etc/ssl/private/api.key;
}
==== Apache: Dual Certificate ====
ServerName api.example.com
# Modern clients -> Hybrid
SSLCertificateFile /etc/ssl/certs/api-hybrid.pem
SSLCertificateKeyFile /etc/ssl/private/api.key
SSLCertificateChainFile /etc/ssl/certs/hybrid-chain.pem
ServerName api-legacy.example.com
# Legacy clients -> Classic
SSLCertificateFile /etc/ssl/certs/api-classic.pem
SSLCertificateKeyFile /etc/ssl/private/api.key
SSLCertificateChainFile /etc/ssl/certs/classic-chain.pem
----
===== Trust Store Management =====
==== Clients with Both CAs ====
# Trust store with both root CAs
cat /etc/pki/classic/root-ca.pem /etc/pki/hybrid/root-ca.pem > /etc/ssl/certs/ca-bundle.pem
# Or add individually
update-ca-trust extract
==== Windows Trust Store ====
# Import both root CAs
Import-Certificate -FilePath "classic-root.cer" -CertStoreLocation Cert:\LocalMachine\Root
Import-Certificate -FilePath "hybrid-root.cer" -CertStoreLocation Cert:\LocalMachine\Root
----
===== CRL/OCSP for Both PKIs =====
# CRL Distribution Points
# Classic: http://crl.example.com/classic/intermediate.crl
# Hybrid: http://crl.example.com/hybrid/intermediate.crl
# Nginx for CRL distribution
location /crl/classic/ {
alias /etc/pki/classic/crl/;
types { application/pkix-crl crl; }
}
location /crl/hybrid/ {
alias /etc/pki/hybrid/crl/;
types { application/pkix-crl crl; }
}
----
===== Monitoring =====
# Prometheus: Monitor both PKIs
scrape_configs:
- job_name: 'pki-classic'
static_configs:
- targets: ['localhost:9793']
params:
path: ['/etc/pki/classic/issued/*.pem']
relabel_configs:
- target_label: pki
replacement: 'classic'
- job_name: 'pki-hybrid'
static_configs:
- targets: ['localhost:9793']
params:
path: ['/etc/pki/hybrid/issued/*.pem']
relabel_configs:
- target_label: pki
replacement: 'hybrid'
**Dashboard Metrics:**
| Metric | Classic | Hybrid |
|--------|---------|--------|
| Active certificates | ''count(x509{pki="classic"})'' | ''count(x509{pki="hybrid"})'' |
| Expiring < 30d | ''count(...)'' | ''count(...)'' |
| CRL Next Update | ''crl_next_update{pki="classic"}'' | ''crl_next_update{pki="hybrid"}'' |
----
===== Migration Tracking =====
#!/bin/bash
# migration-status.sh - Migration progress
echo "=== PKI Migration Status ==="
classic_count=$(find /etc/pki/classic/issued -name "*.pem" | wc -l)
hybrid_count=$(find /etc/pki/hybrid/issued -name "*.pem" | wc -l)
total=$((classic_count + hybrid_count))
if [ "$total" -gt 0 ]; then
hybrid_percent=$((hybrid_count * 100 / total))
else
hybrid_percent=0
fi
echo "Classic: $classic_count"
echo "Hybrid: $hybrid_count"
echo "Total: $total"
echo "Migration: $hybrid_percent%"
# Graphical representation
echo ""
echo -n "Progress: ["
for i in $(seq 1 50); do
if [ $i -le $((hybrid_percent / 2)) ]; then
echo -n "#"
else
echo -n "-"
fi
done
echo "] $hybrid_percent%"
----
===== Phase-Out Classic =====
flowchart LR
subgraph ACTIVE["ACTIVE"]
A1[Both PKIs active]
end
subgraph TRANSITION["TRANSITION"]
T1[Classic: renewal only]
T2[Hybrid: new certificates]
end
subgraph SUNSET["SUNSET"]
S1[Classic: still active only]
S2[No new classic certs]
end
subgraph END["END"]
E1[Classic deactivated]
end
ACTIVE --> TRANSITION --> SUNSET --> END
style ACTIVE fill:#e8f5e9
style END fill:#ffebee
**Timeline:**
| Phase | Action | Trigger |
|-------|--------|---------|
| Active | Both PKIs issuing | Start |
| Transition | Classic renewal only | 80% Hybrid |
| Sunset | Classic only expire | 95% Hybrid |
| End | Classic CA offline | All classic expired |
----
===== Checklist =====
| # | Checkpoint | Done |
|---|------------|------|
| 1 | Both PKIs set up | |
| 2 | Dual-issue scripts work | |
| 3 | Trust stores contain both CAs | |
| 4 | CRL/OCSP available for both | |
| 5 | Monitoring active for both | |
| 6 | Migration tracking set up | |
| 7 | Phase-out plan documented | |
----
===== Related Documentation =====
* [[.:classic-to-hybrid|Classic -> Hybrid]] - Direct migration
* [[.:rollback-strategie|Rollback Strategy]] - Emergency plan
* [[..:monitoring:start|Monitoring]] - Monitor both PKIs
----
<< [[.:classic-to-hybrid|<- Classic -> Hybrid]] | [[.:rollback-strategie|-> Rollback Strategy]] >>
----
//Wolfgang van der Stille @ EMSR DATA d.o.o. - Post-Quantum Cryptography Professional//
{{tag>migration parallel dual-pki compatibility operator}}