Skip to content

Cloudflare Workers 新增后量子加密算法支持 ​

译注:本文翻译自 Cloudflare 官方博客,原文发布于 2026 年 10 月 1 日,作者 Thibault Meunier。原文链接见文末。

Cloudflare Workers 今日宣布在 Web Crypto 中新增对后量子抗性算法的支持。这些算法定义于 W3C 社区组报告草案《Modern Algorithms in the Web Cryptography API》,具体包括:

  • ML-KEM-768 与 ML-KEM-1024:用于密钥封装
  • ML-DSA-44、ML-DSA-65、ML-DSA-87:用于签名
  • 新增 encapsulateBits()、decapsulateBits()、encapsulateKey()、decapsulateKey() 方法
  • 新增 getPublicKey() 辅助方法
  • 新增 SubtleCrypto.supports() 能力检测
  • 支持这些算法的 JWK 导入与导出

对于正在为后量子迁移做准备的开发者而言,这些可选的 Web Crypto API 让实验 ML-KEM 与 ML-DSA 变得更加容易,无需再打包独立的密码学实现。它们并非完整的迁移路径,而是可用于验证集成方案的构建模块。由于相关规范仍在演进中,该支持目前位于 webcrypto_modern_algorithms 兼容性标志之后。

背景 ​

Web Crypto 是一类只有在缺少所需原语时才会被注意到的 API。如果想在 JavaScript 环境中实验较新的后量子算法,过程相当困难:要么无法直接在 Web Crypto 之上构建协议,要么必须自带 JavaScript 或 WebAssembly 密码学实现。这两种选择都不理想——它们把选择和维护密码学实现的负担转嫁给了实现者,导致应用因打包密码学代码而体积膨胀,而且这项工作需要在所有下游库中重复进行。

随着生态系统需要比预期更早地迁移到后量子抗性算法,开发者现在就需要访问这些原语,以便测试、评估和改进后量子集成方案。

快速上手 ​

以下是 ML-KEM 在 Workers 中的用法。一方持有公钥,另一方将共享密钥封装到该公钥;私钥持有者解封装后得到相同的密钥。

javascript
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(Hybrid Public Key Encryption)等协议随后将该材料送入密钥调度和 AES-GCM 等 AEAD 算法。

ML-DSA 则更接近开发者熟悉的 Ed25519 或 ECDSA:生成密钥对、签名、验签。

javascript
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,
);

这些示例刻意保持精简。它们不是协议,而是协议所需的密码学原语的 JavaScript 接口。

为什么这很重要 ​

后量子迁移不是一次开关切换,而是大量协议、库、服务和部署环境学习使用不同原语的过程。部分工作已在 TLS 和 SSH 中显现:OpenSSH 于 2024 年添加了 mlkem768x25519 支持;HPKE 在 IETF 有正在推进的后量子与混合 KEM 草案;IETF 发布了 ML-DSA 在 JOSE 中的 RFC 9964,以及使用 PQ 与 PQ/T HPKE 的 JWE 采纳草案。HTTP Message Signatures 也可以使用不同的签名算法,只要签名方和验证方就签名生成与验证方式达成一致。

要在 Cloudflare Workers 上支持这一切,开发者需要在 Web Crypto 中获得底层密码学原语的支持。否则,Workers 开发者虽然仍可实验后量子代码,但必须打包独立实现——这对可移植性和早期实验有用,却不是我们希望每个生产应用最终停留的状态。

用 ML-DSA 签名 JWT ​

签名 JSON Web Token(JWT)是使用 JSON Web Signature(JWS)保护的常见示例。借助将 ML-DSA-* 算法映射到 Web Crypto 的 panva/jose 库,应用代码如下:

javascript
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);

JWT 只是一个例子。更重要的是,库可以将 ML-DSA 操作委托给运行时,而不必为每个环境携带自己的实现。

HPKE 与 OHTTP ​

ML-KEM 是一种密钥封装机制,单独使用时为双方提供共享密钥材料。HPKE 通过添加密钥调度和 AEAD 将其转化为完整的加密构造。panva/hpke 等库已围绕 Web Crypto 和运行时支持进行构建。当 Workers 运行时暴露 ML-KEM 后,HPKE 实现可以在可用时使用原生原语。

javascript
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,
);

这也是我们希望 OHTTP 等协议呈现的形态。OHTTP 使用 HPKE,如果 HPKE 能通过 Web Crypto 使用后量子 KEM,那么对等方就可以开始讨论迁移到支持这些原语的密码套件。

从私钥获取公钥 ​

若干协议需要在加载私钥后发布或派生公钥。过去这通常意味着同时保留两者,或进行格式特定处理。新的 getPublicKey() 辅助方法直接完成这件事:

javascript
const publicKey = await crypto.subtle.getPublicKey(privateKey, ["verify"]);

对于 ML-KEM,用法有所不同,因为公钥用于封装、私钥用于解封装:

javascript
const publicKey = await crypto.subtle.getPublicKey(privateKey, [
  "encapsulateBits",
]);

检测支持情况 ​

由于该 API 尚未在所有运行时中支持,库应当检测其是否存在,而不是假设它处处可用。

javascript
if (SubtleCrypto.supports("sign", "ML-DSA-44")) {
  const keys = await crypto.subtle.generateKey("ML-DSA-44", false, [
    "sign",
    "verify",
  ]);
}

当前支持范围 ​

初始 Workers 实现支持 ML-KEM-768 作为 KEM、ML-DSA-44 作为签名算法,均需设置 webcrypto_modern_algorithms 标志:

jsonc
{
  // Opt into modern crypto algorithms
  "compatibility_flags": [
    "webcrypto_modern_algorithms"
  ]
}

为完整起见,也支持 ML-KEM-1024、ML-DSA-65 和 ML-DSA-87。ML-KEM-512 不受支持,因为 Workers 使用的 BoringSSL 版本未暴露该变体。最新支持列表可在开发者文档中查阅。

实现方式 ​

Workers 运行在 workerd 上,这是一个基于 V8 的开源运行时。该实现为 workerd 的 Web Crypto 层添加了 ML-KEM 和 ML-DSA 支持,底层由 BoringSSL 原语支撑。此次变更还添加了现代算法 API 表面的 Web Platform Tests、针对兼容性标志行为的 Workers 专属测试,以及新 Workers 类型下的 TypeScript 定义。

该工作从 panva 的一个更大提案中拆分而来,聚焦于 ML-KEM、ML-DSA、辅助 API 和 JWK 支持。WICG 提案中的其他算法(如 SHA-3、cSHAKE、TurboSHAKE、ChaCha20-Poly1305)不在本次初始变更范围内。

需要注意的是,ML-DSA 的公钥和签名比 RSA 或 Ed25519 大得多。在运行时中集成这些算法提升了性能并减少了打包需求,但并未改变密钥、签名或密文在传输或存储时体积增大的现实。

后续可能 ​

WICG 提案涵盖的内容不止 ML-KEM 和 ML-DSA。以下来自 Filip Skokan 在 cloudflare/workerd#6403 中原始贡献的内容尚未实现,需要进一步审查:SHA-3 哈希函数、ChaCha20-Poly1305 AEAD、cSHAKE、TurboSHAKE 以及 HPKE。已有实现针对 panva/hpke 和 panva/jose 测试套件进行了验证。

此外还有一个实际问题:何时将其变为默认而非可选。目前所有这些算法都位于兼容性标志之后。该 API 基于草案,我们希望先获得库作者的反馈,再将其视为稳定。

原文链接 ​

https://blog.cloudflare.com/workers-ml-kem-ml-dsa-support/