原文标题: Support for modern cryptographic algorithms in Workers
作者: Thibault Meunier
来源: Cloudflare Blog 原文
原文日期: 2026 年 10 月 1 日
Cloudflare Workers 为 Web Crypto 增加了若干后量子密码算法接口,使开发者可以在 Worker 运行时中试验 ML-KEM 密钥封装和 ML-DSA 数字签名。它们属于仍在演进的 Web Crypto 现代算法草案,因此目前通过兼容性标志显式启用。它们提供的是构造更完整协议所需的密码学原语,并不意味着应用已经完成后量子迁移。
为什么在 Web Crypto 中提供这些原语
在 JavaScript 环境中试验新的后量子算法,过去通常需要自己把协议拼在现有 Web Crypto 接口上,或额外打包 JavaScript、WebAssembly 密码库。这样会把选择、维护实现的责任交给应用和下游库,也会增大应用包体。若运行时直接提供底层原语,采用 Web Crypto 的库便有机会复用运行时能力,而不必为每个环境附带一份实现。
后量子迁移涉及协议、库、服务和部署环境,不能通过打开一个开关一次完成。Workers 此次提供的构件包括:
- ML-KEM-768、ML-KEM-1024:密钥封装;
- ML-DSA-44、ML-DSA-65、ML-DSA-87:数字签名;
- encapsulateBits()、decapsulateBits()、encapsulateKey()、decapsulateKey();
- getPublicKey() 与 SubtleCrypto.supports();
- 这些算法的 JWK 导入和导出支持。
初始实现的接口仍是 opt-in,因为它依据的规格还在变化,Cloudflare 希望库作者先实际检验并反馈。
ML-KEM:协商共享密钥材料
ML-KEM 是密钥封装机制。接收方先持有公私钥;发送方使用公开密钥封装出共享密钥材料和密文;持有私钥的一方再解封装密文,得到相同的共享密钥材料。下面的简化示例展示 ML-KEM-768 的基本调用:
const keys = await crypto.subtle.generateKey("ML-KEM-768", true, [
"encapsulateBits",
"decapsulateBits",
]);
const { sharedKey, ciphertext } = await crypto.subtle.encapsulateBits(
"ML-KEM-768",
keys.publicKey,
);
const sameSharedKey = await crypto.subtle.decapsulateBits(
"ML-KEM-768",
keys.privateKey,
ciphertext,
);
这段代码还没有加密应用数据。ML-KEM 只给通信双方提供共享密钥材料。像混合公钥加密(HPKE)这样的协议还要通过密钥调度,并使用 AES-GCM 之类的认证加密算法,才能构成完整的加密方案。把密钥封装结果误当成“已经加密的消息”是不对的。
ML-DSA:签名并验证字节
ML-DSA 的使用形态接近 Ed25519 或 ECDSA:生成密钥对,对字节签名,再使用公钥验证。下例与原文展示的接口相对应:
const data = new TextEncoder().encode("hello post-quantum");
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,
);
这类代码同样只是原语示范,不是可直接用于生产的协议设计。真正集成时还需要确定消息编码、密钥管理、算法协商和协议层行为。
与常见协议和库集成
后量子算法正逐步进入协议生态:OpenSSH 已支持混合 ML-KEM 与 X25519 的方案;HPKE 相关工作也在推进后量子和混合 KEM;ML-DSA 已有用于 JOSE 的规范工作。要让这些协议在 Workers 上使用相应算法,运行时需要具备底层密码原语。
例如,jose 可以把 ML-DSA 用于签名 JWT。原文示例的核心流程如下:
import * as jose from "jose";
const alg = "ML-DSA-44";
const { publicKey, privateKey } = await jose.generateKeyPair(alg);
const jwt = await new jose.SignJWT({ sub: "alice" })
.setProtectedHeader({ alg })
.setIssuedAt()
.setExpirationTime("5m")
.sign(privateKey);
await jose.jwtVerify(jwt, publicKey);
库可以把签名操作交给运行时,而不必为所有环境打包自有实现。使用 ML-KEM 的 HPKE 也类似:由库选择运行时可用的 Web Crypto 实现,再组合 KEM、密钥派生函数和 AEAD。下面是原文给出的调用结构:
import * as HPKE from "hpke";
const plaintext = new TextEncoder().encode("Hello World!");
const suite = new HPKE.CipherSuite(
HPKE.KEM_ML_KEM_768,
HPKE.KDF_HKDF_SHA256,
HPKE.AEAD_AES_128_GCM,
);
const recipient = await suite.GenerateKeyPair();
const sealed = await suite.Seal(recipient.publicKey, plaintext);
const opened = await suite.Open(
recipient.privateKey,
sealed.encapsulatedSecret,
sealed.ciphertext,
);
运行时支持原语并不保证每个库都无需改动;库可能需要针对具体运行时做集成适配。原文特别指出,HPKE 库可以根据环境选择实现。
从私钥取得公钥,并检查运行时能力
有些协议需要在加载私钥后发布或推导对应的公钥。新增的 getPublicKey() 可以直接完成此事。签名密钥可请求 verify 用途的公钥:
const publicKey = await crypto.subtle.getPublicKey(privateKey, ["verify"]);
ML-KEM 的用途不同:公钥用于封装,私钥用于解封装,因此取得公钥时应请求 encapsulateBits:
const publicKey = await crypto.subtle.getPublicKey(privateKey, [
"encapsulateBits",
]);
这些现代算法并非所有 JavaScript 运行时都支持。跨 Workers、Node.js、Deno、浏览器等环境运行的库应在调用前检查能力,而不是假定接口普遍存在:
if (SubtleCrypto.supports("sign", "ML-DSA-44")) {
const keys = await crypto.subtle.generateKey("ML-DSA-44", false, [
"sign",
"verify",
]);
}
能力检查也有助于处理“部分实现”:某个运行时可能只实现提案的一部分。
在 Workers 中启用和当前支持范围
使用这些算法需要在 wrangler.jsonc 中加入兼容性标志:
{
// Opt into modern crypto algorithms
"compatibility_flags": [
"webcrypto_modern_algorithms"
]
}
文章列出的初始实现包括 ML-KEM-768 和 ML-DSA-44,并说明 ML-KEM-1024、ML-DSA-65、ML-DSA-87 也可用;ML-KEM-512 不受支持,因为 Workers 使用的 BoringSSL 版本没有公开这一变体。该实现选择使用原生密码库已提供的算法,没有为缺少的变体另行加入一套实现。支持清单应以 Cloudflare 开发者文档的当前版本为准。
Workers 运行在基于 V8 的 workerd 上。此次实现把 ML-KEM 和 ML-DSA 接入 workerd 的 Web Crypto 层,由 BoringSSL 原语提供支持;同时加入了现代算法 API 的 Web Platform Tests、兼容性标志相关测试,以及相应的 Workers TypeScript 类型。
这次改动是较大 Web Crypto 现代算法提案中的一部分,聚焦 ML-KEM、ML-DSA、辅助接口和 JWK 支持。SHA-3、cSHAKE、TurboSHAKE、ChaCha20-Poly1305 等其他提案内容不在此次实现范围内,HPKE 也不是这次 Workers 原生 Web Crypto 改动所实现的算法接口。
实验前需要留意的限制
ML-DSA 公钥和签名明显大于 RSA 或 Ed25519 对应数据。运行时集成可以减少应用重复携带密码实现,但不会消除密钥、签名和密文在传输或存储时变大的事实。
这些 API 仍由 webcrypto_modern_algorithms 标志控制,规格还处于草案阶段。现阶段适合验证库和协议集成、反馈接口问题;不能据此认定现有业务协议已自动获得后量子安全,也不能把 ML-KEM 示例单独当作消息加密协议。若要面向实际系统迁移,需要进一步确认所用协议、对端能力、密钥与数据格式、运行时支持情况,以及密钥/签名体积对网络和存储的影响。
作者致谢: 原文感谢 Filip Skokan 的最初贡献与迭代,感谢 Felix Hanau、James Snell、Bas Westerbaan、Peter Wu 参与审阅,并感谢 Daniel Huigens 共同撰写该实现所依据的规范工作。
来源说明: 本文依据 Cloudflare Blog 指定原文整理与中文化。原文说明该接口基于仍在演进的草案并需显式启用;正文未列出单篇转载许可声明。本文保留原始作者和链接。











暂无评论内容