ML-KEM and ML-DSA Post-Quantum Crypto Come to Workers, One Flag to Opt In
Hi, Shii-chan here! You can now try post-quantum cryptography on Workers!
Cloudflare BlogWhat was announced?
The Cloudflare Blog announced that Workers now has opt-in support for the post-quantum-resistant algorithms ML-KEM and ML-DSA through the Web Crypto APIs. You can try them today.
Why it matters
You can now use cryptography built for a future with quantum computers inside Workers, through the standard Web Crypto API. The implementation lives in workerd (Cloudflare's open-source, V8-based runtime) and is backed by BoringSSL primitives, so you do not need to bundle a separate crypto library. This improves performance and reduces app size compared with JavaScript or WebAssembly implementations.
What changes
You can validate integrations with ML-KEM and ML-DSA using a native implementation, without adding a crypto library. The post is clear that these are building blocks to validate your integration, not a full migration path.
Dive Deep
What's supported
- Key encapsulation: ML-KEM-768 and ML-KEM-1024
- Digital signatures: ML-DSA-44, ML-DSA-65, and ML-DSA-87
- Helper functions:
encapsulateBits(),decapsulateBits(),encapsulateKey(),decapsulateKey(),getPublicKey(),SubtleCrypto.supports(), and JWK import/export for these algorithms
ML-KEM-512 is not included because the underlying BoringSSL library does not expose it.
How to opt in
Add the compatibility flag to your wrangler.jsonc. It is required for now because the specification is still a draft.
{
"compatibility_flags": [
"webcrypto_modern_algorithms"
]
}
Code example (ML-KEM)
const keys = await crypto.subtle.generateKey("ML-KEM-768", true, [
"encapsulateBits",
"decapsulateBits",
]);
const { sharedKey, ciphertext } = await crypto.subtle.encapsulateBits(
"ML-KEM-768",
keys.publicKey,
);
Code example (ML-DSA)
const { publicKey, privateKey } = await crypto.subtle.generateKey(
"ML-DSA-44",
false,
["sign", "verify"],
);
const signature = await crypto.subtle.sign("ML-DSA-44", privateKey, data);
const valid = await crypto.subtle.verify(
"ML-DSA-44",
publicKey,
signature,
data,
);
Runtime support detection
if (SubtleCrypto.supports("sign", "ML-DSA-44")) {
// Use native implementation
}
Limitations
- Size overhead: ML-DSA public keys and signatures are substantially larger than RSA or Ed25519, which affects transmission and storage
- Partial implementation: this is the first part of the modern Web Crypto algorithm specification, and it does not include SHA-3, cSHAKE, TurboSHAKE, or ChaCha20-Poly1305
- Building blocks: these APIs do not provide a full migration path
- Draft specification: explicit opt-in through a compatibility flag is required until the spec is finalized
Wrap-up
- Workers Web Crypto gains ML-KEM-768 / 1024 and ML-DSA-44 / 65 / 87
- Opt in with the
webcrypto_modern_algorithmscompatibility flag - Watch the limitations, such as larger signatures and public keys
This is for anyone who wants to validate post-quantum readiness on Workers early!