# Classic vs Post-Quantum Crypto
ECDSA P-256 vs ML-DSA-65 across the full batch-size sweep (1–1024) on the
same machine. Both use the same algorithm for CA and subscriber keys.
ML-DSA-65 certificates are ~5.5 KB vs ~900 B for P-256.
`cert_gen` builds TBS once using the cached `sig_alg_der`, signs with
`sign_tbs_erased`, and assembles — the TBS DER (which embeds the ~2.5 KB
ML-DSA-65 SPKI) is encoded exactly once per certificate.
## cert_gen — certificate issuance (subscriber keygen + CA sign)
| 1 | 0.600 | 1.7 K | 1.714 | 0.6 K | 2.9× |
| 2 | 0.255 | 7.8 K | 2.378 | 0.8 K | 9.3× |
| 4 | 0.204 | 19.6 K | 1.394 | 2.9 K | 6.8× |
| 8 | 0.313 | 25.6 K | 2.528 | 3.2 K | 8.1× |
| 16 | 0.306 | 52.2 K | 3.521 | 4.5 K | 11.5× |
| 32 | 0.459 | 69.8 K | 6.932 | 4.6 K | 15.1× |
| 64 | 0.532 | 120.3 K | 15.952 | 4.0 K | 30.0× |
| 128 | 0.752 | 170.1 K | 16.082 | 8.0 K | 21.4× |
| 256 | 3.704 | 69.1 K | 23.024 | 11.1 K | 6.2× |
| 512 | 4.510 | 113.5 K | 44.852 | 11.4 K | 9.9× |
| 1024 | 7.354 | 139.2 K | 107.927 | 9.5 K | 14.7× |
## cert_verify — certificate signature verification
| 1 | 0.274 | 3.6 K | 0.317 | 3.2 K | 1.2× |
| 4 | 0.203 | 19.7 K | 0.278 | 14.4 K | 1.4× |
| 16 | 0.185 | 86.3 K | 0.331 | 48.4 K | 1.8× |
| 64 | 1.279 | 50.0 K | 1.941 | 33.0 K | 1.5× |
| 256 | 5.049 | 50.7 K | 3.764 | 68.0 K | 0.7× |
| 1024 | 8.004 | 127.9 K | 17.310 | 59.2 K | 2.2× |
## ocsp_sign — OCSP response signing (N parallel responses)
| 1 | 0.032 | 31.4 K | 0.505 | 2.0 K | 15.9× |
| 4 | 0.165 | 24.2 K | 1.861 | 2.1 K | 11.3× |
| 16 | 0.227 | 70.6 K | 4.465 | 3.6 K | 19.7× |
| 64 | 0.241 | 265.1 K | 10.259 | 6.2 K | 42.5× |
| 256 | 1.109 | 230.9 K | 19.109 | 13.4 K | 17.2× |
| 1024 | 2.438 | 420.0 K | 77.121 | 13.3 K | 31.6× |
## ocsp_verify — OCSP response verification
| 1 | 0.089 | 11.2 K | 0.138 | 7.2 K | 1.5× |
| 4 | 0.239 | 16.7 K | 0.280 | 14.3 K | 1.2× |
| 16 | 0.529 | 30.2 K | 0.398 | 40.2 K | 0.8× |
| 64 | 2.000 | 32.0 K | 2.011 | 31.8 K | 1.0× |
| 256 | 5.343 | 47.9 K | 4.496 | 56.9 K | 0.8× |
| 1024 | 8.881 | 115.3 K | 15.491 | 66.1 K | 1.7× |
## crl_sign — CRL signing (1 CRL per batch, N revoked serials)
| 1 | 0.031 | 32.5 K | 0.261 | 3.8 K | 8.5× |
| 8 | 0.041 | 24.5 K | 0.261 | 3.8 K | 6.4× |
| 64 | 0.243 | 4.1 K | 0.754 | 1.3 K | 3.1× |
| 256 | 0.132 | 7.6 K | 1.622 | 0.6 K | 12.3× |
| 1024 | 0.439 | 2.3 K | 1.495 | 0.7 K | 3.4× |
## db_insert_certs / db_read_certs — SQLite I/O
| 1 | 0.043 | 0.045 | 1.1× | 0.030 | 0.030 | 1.0× |
| 16 | 0.086 | 0.195 | 2.3× | 0.037 | 0.075 | 2.0× |
| 64 | 0.637 | 1.356 | 2.1× | 0.225 | 0.622 | 2.8× |
| 256 | 1.012 | 4.658 | 4.6× | 0.615 | 0.478 | 0.8× |
| 1024 | 4.077 | 16.688 | 4.1× | 0.613 | 2.760 | 4.5× |
## Analysis
**Signing (cert_gen, ocsp_sign)** shows the largest asymmetry, with high
variability across batch sizes driven by Rayon scheduling:
- At **small batches (1–8)**, P-256 operations finish before the Rayon thread
pool is fully loaded, so the ratio is relatively low (3–10×).
- At **medium batches (16–64)**, P-256 saturates the thread pool first and
benefits from full parallelism while ML-DSA-65 is still ramping up —
producing the highest ratios (15–42× for `ocsp_sign`, 11–30× for `cert_gen`).
- At **large batches (256–1024)**, ML-DSA-65 also saturates the pool, and the
ratio settles in the 10–20× range for signing operations.
`cert_gen` ratios are lower than `ocsp_sign` ratios at the same batch size
because `cert_gen` bundles subscriber key generation (which is faster for
both algorithms) with CA signing, diluting the signing cost.
**Verification (cert_verify, ocsp_verify)** shows a fundamentally different
picture — ML-DSA-65 and P-256 are within 1–2× across all batch sizes:
- This reflects a core ML-DSA property: signing requires expensive lattice
sampling (slow), while verification is a single NTT-based matrix-vector
check (fast). ECDSA has more symmetric sign/verify costs.
- At batch=256 both `cert_verify` and `ocsp_verify` show ML-DSA-65 *faster*
than P-256 (0.7–0.8× ratio) — Rayon scheduling noise at this batch size.
**DER payload size effect (db_insert_certs, db_read_certs):**
- Insert cost scales with DER size: ML-DSA-65 certs are ~6× larger (5.5 KB
vs ~900 B), and the insert ratio grows from 1.1× at batch=1 to ~4.1–4.6×
at batch=512–1024 as WAL write volume dominates.
- Read cost shows a similar but noisier pattern; at batch=256 ML-DSA-65 reads
faster than P-256 (SQLite page-cache effect at this specific data size).
**CRL signing** ratios are noisy (only one signing operation per batch,
no Rayon parallelism): 3–12× depending on batch size. At large batches
(64–1024) the TBS DER encoding cost grows proportionally (more revoked serial
entries), gradually reducing the signing-time fraction for P-256 and narrowing
the ratio to 3–4×.