RPCScan
4,973 networks tracked8,054 RPC URLsRequestStatus
Companion site:ExplorerScan ↗Block explorer directory with per-provider drill-downs and TLS posture per host

Security & Post-Quantum Posture

What we ship, what we measure, and what is honestly impossible right now — in detail.

TL;DR

  • Browser ↔ rpcscan.com: post-quantum hybrid key exchange via the Cloudflare edge (X25519MLKEM768), classical certificate authentication. The strongest public-WebPKI posture available in 2026.
  • RPCScan prober ↔ public RPC endpoints: our own hand-rolled TLS 1.3 client (bn-tls) negotiates pure post-quantum (MLKEM1024) where the upstream supports it, three different post-quantum hybrids where it does not, classical X25519 only as a last-resort fallback.
  • Per-probe telemetry: every successful handshake records which IANA NamedGroup was negotiated. Browse /pq-adoption for the live tracker, or /security/<rpc-url> for any specific endpoint.

Why "fully post-quantum web" is not a thing yet

A TLS 1.3 connection has two independent cryptographic axes: key exchange (the shared secret encrypting the session) and authentication (the certificate proving the server's identity). Post-quantum protection is a per-axis property.

Key exchange went post-quantum in 2024. Cloudflare, Google, Apple, Mozilla, AWS and Squarespace all ship at least one IETF-standardized hybrid built on ML-KEM (FIPS 203). The shared secret is the concatenation of a classical ECDH result and an ML-KEM KEM result, fed into the standard TLS 1.3 HKDF schedule. A future cryptographically-relevant quantum computer that captured today's handshake still cannot recover the session key — it would have to break both halves.

Authentication is still classical, and that is not our choice to make. No public Certificate Authority issues ML-DSA (Dilithium, FIPS 204) certificates. Browsers do not trust them. The IETF LAMPS working group has draft specs for ML-DSA in X.509, but no production CA pipeline exists. Until that ships, every public website — including ours — authenticates with ECDSA-P256 or RSA-PKCS1.

So: anyone advertising "fully post-quantum HTTPS" for a public-web property in 2026 is either using a custom client (not a normal browser) or being imprecise. The accurate claim is "post-quantum hybrid (or pure) key exchange with classical authentication" — which is exactly what we ship, and exactly what the major edges ship.

The five tiers we negotiate

Our prober's ClientHello offers five named groups in the order below. We send a pre-emptive key_share entry for every one of them, so regardless of which group the server selects, we already have the matching keypair and never need a HelloRetryRequest round-trip. (Trade-off: a ~5.3KB ClientHello.)

TierGroupCodepointWire formatSeen on
pure-PQMLKEM10240x0202MLKEM_ek(1568) → MLKEM_ct(1568)Google (gmail, youtube)
hybridSecP384r1MLKEM10240x11EDP384(97)‖MLKEM_ek(1568)Squarespace, AWS (optional)
hybridX25519MLKEM7680x11ECMLKEM_ek(1184)‖X25519(32) *Cloudflare default, Google, AWS, Apple, Mozilla — ~99.99% of PQ-enabled sites
hybridSecP256r1MLKEM7680x11EBP256(65)‖MLKEM_ek(1184)AWS
classicalX255190x001DX25519(32)Self-hosted RPC nodes that haven't enabled PQ yet

* X25519MLKEM768 reverses the convention used by the other two hybrids: ML-KEM goes first in both the wire encoding and the shared secret concatenation. The other hybrids put ECDH first. This is per draft-ietf-tls-ecdhe-mlkem-04 and matches Cloudflare CIRCL's reference implementation.

Live posture: what we negotiate against the major providers

Sampled from our last smoke run:

EndpointNegotiated groupClass
www.google.comMLKEM1024pure post-quantum
mail.google.comMLKEM1024pure post-quantum
youtube.comMLKEM1024pure post-quantum
cloudflare.comX25519MLKEM768PQ hybrid
www.amazon.comX25519MLKEM768PQ hybrid
www.squarespace.comX25519MLKEM768PQ hybrid
eth.llamarpc.comX25519MLKEM768PQ hybrid
cloudflare-eth.comX25519MLKEM768PQ hybrid
ethereum-rpc.publicnode.comX25519MLKEM768PQ hybrid
rpc.ankr.comX25519classical
api.mainnet-beta.solana.comX25519classical

We measure PQ key exchange on every public RPC endpoint and, with the same handshake test, on the Tranco Top-1M every day. Current figures for both are on crypto RPC vs. the open web.

Per-probe telemetry pipeline

Every probe our system performs records the negotiated group and cipher suite into ClickHouse. The data flows:

  1. bn-tls finishes the handshake and exposes negotiated_group() / pq_class() / cipher_suite_name().
  2. bn-http attaches a TlsInfo to every ClientResponse.
  3. The prober's per-kind Outcome records tls_group / tls_pq_class / tls_cipher_suite alongside latency / block-height / etc.
  4. Each row is written to ClickHouse probe_results; two materialized views fan it out: tls_endpoint_latest (ReplacingMergeTree, newest posture per endpoint) and tls_adoption_daily (AggregatingMergeTree with uniqState per (day, group, pq_class)).
  5. JSON endpoints expose the data: /tls/endpoint?url=…, /tls/endpoint-history?url=…&days=N, /tls/adoption?days=N.
  6. UI: per-RPC card on every /rpc/[id] page, drilldown at /security/[url] with day-by-day adoption strip and transition detection, global tracker at /pq-adoption with a stacked-bar chart of every group's adoption over 180 days.

This is the differentiator: we are not aware of any other public dataset that records the negotiated TLS NamedGroup per RPC endpoint over time. If a CDN flips a flag, you can see the date it happened. If your application has a threat model that rules out classical curves, you can filter for PQ-ready endpoints directly.

Our hand-rolled TLS 1.3 stack

The RPCScan prober talks to thousands of public RPC endpoints continuously. We do not use rustls, openssl, or ring. The whole TLS client — record layer, key schedule, full handshake state machine, X.509 chain validation — is hand-rolled Rust we wrote ourselves, built on audited primitive crates only.

Why bother:

  • Total dependency count is small and auditable — every crate is on an explicit allow-list checked in CI on every commit (currently 126 crates, of which only ~30 actually compile for darwin/linux release builds; the rest are cfg(target_os="wasi")-gated).
  • No async runtime, no TLS framework, no connection pool. Synchronous I/O on libc syscalls.
  • We control the ClientHello shape exactly — ordering, extensions, fingerprint — useful when a CDN's heuristics decide a connection looks "wrong."
  • Every probe records the negotiated cipher suite and key-exchange group, which is how the telemetry above is even possible.

What it speaks:

  • Versions: TLS 1.3 only. No 1.2 fallback. (1.2 cannot do hybrid key exchange and is not forward-secret in the same way.)
  • Key exchange (offered): MLKEM1024, SecP384r1MLKEM1024, X25519MLKEM768, SecP256r1MLKEM768, X25519. secp256r1 / secp384r1 advertised but not selected (no server picks them when better options are on offer).
  • Cipher suites: TLS_AES_128_GCM_SHA256, TLS_CHACHA20_POLY1305_SHA256. Both use SHA-256 for the transcript hash, keeping the key schedule single-path.
  • Signature algorithms (CertificateVerify + chain): ECDSA-P256-SHA256, ECDSA-P384-SHA384, RSA-PKCS1-(256/384/512), RSA-PSS-rsae-(256/384/512), Ed25519. Full verification per RFC 8446 §4.4.3 (64×0x20 prefix &Vert; "TLS 1.3, server CertificateVerify" &Vert; 0x00 &Vert; transcript_hash).
  • Extensions sent: server_name, supported_groups, signature_algorithms, supported_versions, psk_key_exchange_modes (psk_dhe_ke; included for fingerprint compatibility), key_share, application_layer_protocol_negotiation (http/1.1).
  • Out of scope: session resumption, 0-RTT, client certificates, OCSP stapling, SCTs, HTTP/2.

What we explicitly did not do

  • Replace certificate signatures with ML-DSA. No public CA path. Doing this would break trust against every browser and every public RPC. The certificate ecosystem moves on its own schedule; we cannot front-run it.
  • Drop the X25519 fallback. A meaningful fraction of RPC nodes haven't enabled PQ. Removing the fallback would break our own prober for zero security gain — we already protect each connection via full chain validation; downgrade attacks land on a connection we still verify.
  • Build a custom "PQ-only" protocol for the website. Browsers don't speak it. Custom protocols belong in custom clients, not in a public web property meant to be reachable from any device.
  • Implement TLS 1.2. 1.3 is mandatory for forward secrecy guarantees and for hybrid key exchange. If a server only speaks 1.2 we don't talk to it.
  • Implement TLS_AES_256_GCM_SHA384. It requires a SHA-384 transcript path; our entire key schedule is SHA-256. AES-128-GCM is universally supported in 1.3 and there is no security reason to prefer 256-bit AES at the AEAD layer when the rest of the protocol is 128-bit.

What this means for you

If you are reading this in a recent browser, your connection to RPCScan is using post-quantum hybrid key exchange (or pure post-quantum, if you happen to be on a Google property routed through Cloudflare). An adversary recording today's ciphertext and decrypting it with a future cryptographically-relevant quantum computer cannot recover the session contents. The certificate that authenticates the server is still classical — that part of the public web is a few years away from going post-quantum, and the gating factor is the certificate ecosystem, not browsers or servers.

If you are a developer using our prober data, every endpoint we score includes the key-exchange group its TLS handshake actually negotiated, plus a 90-day history of past group selections. You can filter for PQ-ready RPC nodes if your application's threat model requires it. See /pq-adoption for the live tracker, or click any RPC endpoint to see /security/<url> for its full posture.

Cloudflare PQ best-practices alignment

Cloudflare publishes a PQ support matrix listing the algorithms its edge currently deploys. The table below shows how our hand-rolled stack tracks against that matrix, item by item.

Cloudflare itemRPCScan stackStatus
Default key agreement = X25519MLKEM768Advertised + implemented (codepoint 0x11EC)aligned
SecP256r1MLKEM768 (alt hybrid)Advertised + implemented (codepoint 0x11EB)aligned
SecP384r1MLKEM1024 (high-security hybrid)Advertised + implemented (codepoint 0x11ED)aligned
Pure ML-KEM (Google deploys MLKEM1024; CF not yet)Advertised + implemented (codepoint 0x0202)ahead of CF
TLS 1.3 only1.2 fallback explicitly refusedaligned
ML-DSA signature algorithmsNot offered (no public CA issues ML-DSA certs; CF blocked on Merkle Tree Certificates)not yet, by design
X25519MLKEM768 hybrid IKM order: MLKEM_ss ‖ X25519_ssImplemented per RFC-ietf-tls-ecdhe-mlkem-04 §3 (CIRCL ordering)aligned
AES-128-GCM-SHA256 + ChaCha20-Poly1305-SHA256 ciphersBoth advertised + AEAD-dispatched per negotiated suitealigned

Bottom line: every PQ key-agreement algorithm Cloudflare deploys is also offered by our prober, plus pure ML-KEM-1024 which CF doesn’t yet ship but Google does. Signature algorithms intentionally stay classical until CAs and browsers adopt ML-DSA — same posture Cloudflare describes.

References

  • FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard (NIST, 2024).
  • FIPS 204: Module-Lattice-Based Digital Signature Standard (NIST, 2024).
  • RFC 8446: The Transport Layer Security (TLS) Protocol Version 1.3.
  • draft-ietf-tls-ecdhe-mlkem-04: Post-quantum hybrid ECDHE-MLKEM Key Agreement for TLSv1.3 — defines codepoints 0x11EB, 0x11EC, 0x11ED.
  • draft-connolly-tls-mlkem-key-agreement-05: ML-KEM Post-Quantum Key Agreement for TLS 1.3 — defines pure-PQ codepoints 0x0200 (MLKEM-512), 0x0201 (MLKEM-768), 0x0202 (MLKEM-1024).
  • IANA TLS Parameters Registry, NamedGroup: tls-parameters-8.
  • Cloudflare CIRCL X25519MLKEM768 reference implementation: github.com/cloudflare/circl/kem/hybrid.
  • Cloudflare PQ support matrix — canonical list of algorithms CF’s edge deploys: developers.cloudflare.com/ssl/post-quantum-cryptography/pqc-support.
  • J. Schauma, Sites using PQC (February 2026): netmeister.org/blog/pqc-use-2026-02.html.
  • Cloudflare Research PQ test endpoint: pq.cloudflareresearch.com.