Buying and Deploying PQC-Ready Certificates: Providers, ACME, and Nginx
TL;DR
Hybrid PQC key exchange (X25519MLKEM768) is deployable today against an ordinary classical certificate — it's a server-config change, not a purchasing decision. A PQC-signed certificate chain (ML-DSA per FIPS 204) that a public browser actually trusts is a different matter: no major root program has broadly enabled trust for ML-DSA leaf certificates in production yet, because a new signature algorithm at the root of trust requires new roots to be generated, embedded in browsers and OS trust stores, and cross-signed for compatibility — a multi-year process, unlike the software-only rollout hybrid key exchange got. Most CA activity today is test and sandbox issuance, not general availability. ACME itself (RFC 8555) needs no protocol change to carry ML-DSA's larger keys and signatures — its JWS-wrapped, HTTPS-transported messages are already algorithm-agnostic — but client tooling, CA backends, and X.509 OID definitions for PQC algorithms (standardized by the IETF LAMPS working group) all need to catch up before end-to-end issuance is routine.
Market Overview
Certificate authorities are ahead of what they can actually issue for public trust. The CA/Browser Forum is actively drafting Baseline Requirements changes to permit PQC signature algorithms in publicly trusted certificates, and several CAs run sandbox or test ACME endpoints where customers can request hybrid or ML-DSA-signed test certificates ahead of general availability — useful for validating your own stack's readiness, not for production issuance yet. The bottleneck is not cryptographic; it's trust-chain distribution. A root CA's certificate has to be embedded in browsers and operating systems years in advance of being relied upon, so a new ML-DSA root generated today doesn't help a production deployment until that distribution has happened — which is also why hybrid key exchange rolled out first: it required no new trust roots, only a software update on both ends of the TLS connection.
Given how fast CA positions are changing, treat the table below as a snapshot rather than a purchasing reference — verify current status directly with the provider before committing.
Provider Comparison
| Provider | PQC Support Status | Validation Type | Link |
|---|---|---|---|
| SSL.com | Public hybrid / ML-DSA test and sandbox certificates; no general-availability publicly trusted PQC issuance yet | DV, OV, EV (classical); DV/OV in PQC sandbox | [Affiliate Link] |
| DigiCert | PQC readiness toolkit and demo/test issuance for hybrid certificates; GA timeline tied to CA/Browser Forum policy finalization | DV, OV, EV (classical) | [Affiliate Link] |
| Let's Encrypt | No PQC certificate issuance; publicly stated wait-and-see position pending ecosystem-wide root and browser trust readiness | DV only | [Affiliate Link] |
| Namecheap | Reseller (commonly of Sectigo-issued certificates); PQC availability inherits from the underlying issuing CA, not offered as a distinct Namecheap product | DV, OV, EV (resold, classical) | [Affiliate Link] |
The ACME Protocol and Large PQC Payloads
ACME (RFC 8555) doesn't encode any assumption about key or signature size into its message grammar — a CSR is
submitted to the finalize endpoint as a base64url-encoded PKCS#10 DER blob, and ACME messages themselves are
JWS-wrapped JSON transported over ordinary HTTPS. An ML-DSA-65 signature at 3,309 bytes
versus an ECDSA signature's ~70 bytes changes the size of that blob, not the protocol's structure — there is
no ACME-level field limit analogous to TLS's initial congestion window that a large PQC CSR or issued
certificate runs into.
What does need to catch up is everything around the protocol:
- CSR generation. The client generating the certificate signing request needs a crypto backend that can produce an ML-DSA (or hybrid) key pair and sign the CSR with it — this depends on the ACME client's underlying library supporting the algorithm, the same OpenSSL 3.5 dependency that gates server-side hybrid key exchange support.
- X.509 encoding. Representing an ML-DSA or ML-KEM public key inside a certificate's
SubjectPublicKeyInfostructure requires standardized OIDs for those algorithms in X.509 — this is the IETF LAMPS (Limited Additional Mechanisms for PKIX and SMIME) working group's responsibility, and CA backends need to support issuing against those OIDs, not just validate a CSR's signature. - CA-side signing infrastructure. A CA's issuing infrastructure — often HSM-backed — needs PQC algorithm support in the HSM firmware or signing service itself before it can sign an ML-DSA certificate at all, independent of whether its ACME frontend already accepts the request.
One distinction worth being explicit about: the key used to authenticate ACME protocol requests (the account key, used to sign each JWS request to the ACME server) is entirely separate from the key being requested in the certificate. An ACME client can keep an ECDSA account key for protocol authentication while requesting an ML-DSA certificate — there's no requirement that these match, the same decoupling already true of certificate signatures versus TLS key exchange generally.
Nginx Deployment
Deployable today: load your existing classical certificate as usual, and add hybrid key exchange
independently. ssl_ecdh_curve controls the ephemeral key exchange group only — it has no relationship to
what algorithm signed the certificate loaded via ssl_certificate, which is why this works with a certificate
issued by any CA today, PQC-ready or not.
server {
listen 443 ssl;
server_name example.com;
ssl_protocols TLSv1.3;
# Standard certificate loading — no PQC requirement on the
# certificate itself for hybrid key exchange to work.
ssl_certificate /etc/nginx/certs/example.com.crt;
ssl_certificate_key /etc/nginx/certs/example.com.key;
# Hybrid key exchange: X25519MLKEM768 preferred, classical X25519
# as fallback for clients without ML-KEM support.
ssl_ecdh_curve X25519MLKEM768:X25519:prime256v1;
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256;
location / {
proxy_pass http://backend;
}
}Once a CA-issued, publicly trusted ML-DSA certificate is actually obtainable, loading it requires no new
directive — ssl_certificate and ssl_certificate_key accept whatever key type the linked OpenSSL
recognizes, so a future ML-DSA cert bundle drops into the same two lines:
# Forward-looking: once a publicly trusted ML-DSA certificate is
# issuable, it loads through the same directives — no new syntax.
ssl_certificate /etc/nginx/certs/example.com-mldsa.crt;
ssl_certificate_key /etc/nginx/certs/example.com-mldsa.key;Until public trust catches up, the combination worth deploying in production is a classical certificate paired with hybrid key exchange — it captures the actual, currently exploitable risk (Harvest Now, Decrypt Later against recorded key exchanges) without waiting on a certificate market that isn't ready to sell what it doesn't yet trust.