Post-quantum cryptography

RTEdge.net uses post-quantum cryptography in two places. Connections to Elefunc hosts use hybrid post-quantum key agreement, X25519MLKEM768, and edge workers can use ML-KEM and ML-DSA through Web Crypto. Everything else is classical today: sessions are signed with ECDSA P-384 and checked at the edge. This guide says what each part covers, how to check it, and how to detect it from code.

What is post-quantum here

PartStatus today
TLS key agreement to RTEdge.net hostsHybrid post-quantum: X25519MLKEM768, when your browser offers that group.
ML-KEM and ML-DSA in Web Crypto, in edge workersAvailable to every worker uploaded since 2026-10-01.
ML-KEM and ML-DSA in Web Crypto, in playground workersDepends on your browser.
Sessions and other platform signaturesClassical: ECDSA P-384.

TLS to RTEdge.net hosts

RTEdge.net hosts are served by Cloudflare's edge TLS. On 2026-10-04 every host that was checked negotiated the hybrid post-quantum key agreement X25519MLKEM768, TLS group id 4588: elefunc.com, rtedge.net, rtcode.io, new.rt.ht, out.rtcode.io, out.rtcode.net, webpdf.pro, rt.ht and blog.elefunc.com all reported secure: true.

Note: Your own connection uses the hybrid group only when your browser offers it. The check below tests the host, not your browser.

Check a host

The pq type of q.cf.rt.ht asks Cloudflare Radar whether a host supports post-quantum TLS. It takes a comma list of hosts and answers with JSON:

plain
https://q.cf.rt.ht/?pq=rtedge.net,rtcode.io,elefunc.com
https://qi.rt.ht/?pq=elefunc.com,rtedge.net,rtcode.io

The second URL opens the same query in the qi.rt.ht console, which is what the Verify button on elefunc.com links to. A host that supports it answers like this:

js
{ "PQ": { "rtcode.io": { "secure": true, "host": "rtcode.io:443", "kex": { "name": "X25519MLKEM768", "id": 4588 } } } }
secure

true when the host negotiates a post-quantum key agreement.

kex

The key agreement group that the check saw, with its name and TLS group id.

error

When every upstream check fails, the answer for that host is { "error": "PQ test failed for <host>" }.

The service sends Access-Control-Allow-Origin: * and Cache-Control: no-store. A live check takes about a second: on 2026-10-04 it took about 0.7 seconds for three hosts and 1.1 seconds for nine. Load it lazily, and do not call it on every page view.

A live post-quantum badge

The link opens the console for a prepared query. The script prints the key agreement that the check saw for rtcode.io when the host is secure, classical TLS when it is not, and check failed when the answer has no key agreement.

html
<a href="//qi.rt.ht/?pq=rtcode.io,rtedge.net" target=_pq>Verify</a> <output id=badge>…</output>
<script type=module>
  const { PQ } = await fetch('//q.cf.rt.ht/?pq=rtcode.io').then(r => r.json())
  const pq = PQ?.['rtcode.io']
  badge.value = pq?.secure ? `🔐 ${pq.kex.name}` : pq?.kex ? 'classical TLS' : 'check failed'
</script>

ML-KEM and ML-DSA in edge workers

Every worker uploaded to RTEdge.net since 2026-10-01 has the Workers subset of the WICG modern-algorithms draft for Web Crypto: ML-KEM for key encapsulation and ML-DSA for signatures. Elefunc's probe of 40 checks passes 18 of them at the edge.

What is available

AlgorithmOperationsSizes
ML-KEM-768encapsulateBits, encapsulateKey, decapsulateBits and decapsulateKey, with 32-byte shared secretsPublic key 1184 bytes, ciphertext 1088 bytes
ML-KEM-1024The same four operations, with 32-byte shared secretsPublic key and ciphertext 1568 bytes
ML-DSA-44sign and verifySignature 2420 bytes
ML-DSA-65sign and verifySignature 3309 bytes
ML-DSA-87sign and verifySignature 4627 bytes

Around the algorithms, these parts of the draft work too: getPublicKey(), the static SubtleCrypto.supports(), JWK keys with kty: "AKP", the raw-seed, spki and pkcs8 formats, and the ML-DSA context parameter.

What is not available

These throw NotSupportedError at the edge:

  • ML-KEM-512.
  • The hybrid KEMs: X-Wing (MLKEM768-X25519), MLKEM768-P256 and MLKEM1024-P384.
  • SLH-DSA, ChaCha20-Poly1305 and AES-OCB.
  • SHA3-256, SHA3-384, SHA3-512, cSHAKE, TurboSHAKE, KT128 and KT256, KMAC and Argon2.

Which deployments have it

Each upload sets the webcrypto_modern_algorithms compatibility flag, together with the other flags that RTEdge.net always sets. You cannot change the flags. A worker uploaded before 2026-10-01 does not have the flag, so redeploy its route to get it. See Edge worker runtime.

Detect support

At the edge, globalThis.Cloudflare?.compatibilityFlags?.webcrypto_modern_algorithms === true tells you that the flag is set. It works only there. crypto.subtle.constructor.supports?.('encapsulateBits', 'ML-KEM-768') works in both places when supports exists. Trying generateKey() works everywhere, and the example below uses it. Prefer detection to reading version numbers.

A worker that reports its support

In the playground the worker answers according to your browser. Deployed, it answers true for workers uploaded since 2026-10-01.

html
<iframe src=:></iframe>
<script type=worker edge>
  const can = (alg, usages) => crypto.subtle.generateKey(alg, false, usages).then(() => true, () => false)
  export default {
    fetch: async r => Response.json({
      runtime: r.rt.edge ? 'edge' : 'browser',
      flag:    globalThis.Cloudflare?.compatibilityFlags?.webcrypto_modern_algorithms ?? null,
      mlkem768: await can('ML-KEM-768', ['encapsulateBits', 'decapsulateBits']),
      mldsa65:  await can('ML-DSA-65', ['sign', 'verify'])
    })
  }
</script>

In the playground

Worker code in the playground runs in your browser, so it gets the browser's own Web Crypto. The table shows the state reported in the Elefunc blog post of 2026-10-01.

BrowserStatus
Chrome 155ML-KEM-768 and ML-KEM-1024, ML-DSA-44, ML-DSA-65 and ML-DSA-87, X-Wing and ChaCha20-Poly1305 are on by default. The stable rollout starts on October 6. Earlier Chromium versions have none of them.
Edge 155Follows Chrome. It is due the week of October 8.
Firefox 157ML-KEM behind the dom.webcrypto.encapsulation.enabled preference in about:config, without ML-DSA or supports().
SafariNo implementation.

The blog post recommends the hybrid X-Wing, MLKEM768-X25519, where a browser has it. RTEdge.net workers do not have it, so code that must run in both places needs a fallback. Playground and edge differences lists this with the other differences.

What is still classical

Only TLS key agreement and the opt-in Web Crypto algorithms in workers are post-quantum today. Sessions are signed with ECDSA P-384 and checked at the edge, and the other signatures that the platform makes also use ECDSA. Post-quantum key agreement does not make them post-quantum. See Security and access model.

Availability

FeaturePlaygroundRTEdge.netNotes
Hybrid post-quantum TLS key agreementYesYesThe output origins and rtcode.io were checked too. Your browser has to offer the group.
ML-KEM and ML-DSA in Web CryptoPartialYesThe playground depends on your browser. RTEdge.net has it for workers uploaded since 2026-10-01.

See also