Cloudflare Workers 正在加入对 ML-KEM 和 ML-DSA 的可选支持。这两类算法面向后量子安全场景:ML-KEM 用于建立共享密钥,ML-DSA 用于数字签名。由于功能采用 opt-in 方式开放,现有 Worker 不会因为运行时升级而被迫改变密码学行为,团队可以先在测试环境验证兼容性和性能。
两种算法解决的不是同一个问题
ML-KEM 是密钥封装机制(Key Encapsulation Mechanism,KEM)。它的核心用途是让通信双方建立共享秘密,再用这个秘密派生对称密钥。它并不是一个可以直接替换 AES 的“文件加密算法”,也不应被当作普通公钥加密接口使用。
ML-DSA 则是数字签名算法,适合完成两件事:
- 私钥持有者对消息或摘要签名;
- 验证方使用公钥确认数据来源和完整性。
在实际系统中,两者通常处于不同链路。例如,服务间握手可以评估 ML-KEM,构建产物、配置清单或 Webhook 消息则可以评估 ML-DSA。不要因为它们都带有“后量子”标签,就把两个 API 混成同一种用途。
还需要注意,“后量子抗性”表示算法被设计为抵抗已知量子攻击模型,并不意味着实现天然没有风险。随机数质量、密钥生命周期、侧信道、日志泄漏和错误的协议组合,仍然可能让一个算法正确的系统变得不安全。
为什么 opt-in 很重要
密码算法进入边缘运行时,不只是多了两个函数。密钥尺寸、签名长度、计算开销以及上下游协议支持,都可能与现有算法不同。
采用 opt-in 模式至少带来三个好处:
- 避免静默改变现有应用。 老 Worker 可以继续保持原有行为。
- 允许逐环境验证。 团队可以先在开发或预发布环境打开支持,再观察延迟、CPU 时间和错误率。
- 方便做协议协商。 当客户端、边缘节点和源站尚未全部支持新算法时,可以保留经典算法或混合模式作为兼容路径。
这里最容易踩的坑,是只在 Worker 中启用算法,却没有检查调用方和密钥管理系统。边缘代码能够生成 ML-DSA 密钥,不代表现有 HSM、证书系统、数据库字段或消息格式就能正确保存和使用它。
在 Worker 中做一个最小能力探测
下面是一个可以放进现有 Workers 项目的探测端点。它不会把密钥返回给客户端,只检查当前运行时能否识别并生成相应类型的密钥。
假设与边界: 示例假设运行时通过 Web Crypto 风格的 crypto.subtle 暴露算法。算法名称、参数以及具体 opt-in 配置可能随 Workers 当前实现而变化;运行前应按照当前控制台或项目配置启用该能力,并以运行时文档列出的标识符为准。即使名称不匹配,端点也会返回结构化错误,不会让 Worker 崩溃。
将以下内容保存为 src/index.js:
async function probe(label, algorithm, usages) {
const startedAt = performance.now();
try {
const keyPair = await crypto.subtle.generateKey(
algorithm,
false,
usages
);
return {
algorithm: label,
supported: true,
elapsedMs: Number((performance.now() - startedAt).toFixed(2)),
keyTypes: {
publicKey: keyPair.publicKey?.type ?? null,
privateKey: keyPair.privateKey?.type ?? null
}
};
} catch (error) {
return {
algorithm: label,
supported: false,
elapsedMs: Number((performance.now() - startedAt).toFixed(2)),
error: error instanceof Error ? error.message : String(error)
};
}
}
export default {
async fetch(request) {
const url = new URL(request.url);
if (url.pathname !== "/crypto-capabilities") {
return new Response("Not found", { status: 404 });
}
const results = await Promise.all([
probe("ML-KEM-768", { name: "ML-KEM-768" }, []),
probe("ML-DSA-65", { name: "ML-DSA-65" }, ["sign", "verify"])
]);
return Response.json({
runtime: "Cloudflare Workers",
checkedAt: new Date().toISOString(),
results
});
}
};
在已有 Workers 项目中可以这样启动本地开发服务器:
npx wrangler dev
然后从另一个终端调用:
curl -s http://localhost:8787/crypto-capabilities
部署到已启用相应能力的测试环境后,再用实际域名检查:
curl -s https://YOUR-WORKER.example.workers.dev/crypto-capabilities
这个端点适合做一次性验证,但不建议原样公开到生产环境。生产部署前可以增加管理员鉴权,或者在完成兼容性测试后直接删除探测路由。
不要从“能生成密钥”直接跳到生产签名
能力探测通过,只能说明运行时接受对应 API。下一步应验证完整生命周期:
- 密钥在哪里生成、保存和轮换;
- 私钥是否允许导出,以及是否真的需要导出;
- 公钥和签名如何编码、传输与版本化;
- 消费方是否支持相同的算法参数;
- 签名、密文和公钥尺寸是否超过数据库或消息队列限制;
- 失败时是拒绝请求、回退到经典算法,还是进入混合模式;
- 日志、追踪和异常对象中是否可能出现敏感材料。
如果系统需要长期保密,还应优先评估“先记录、后解密”风险:攻击者可能今天保存流量,等未来具备更强计算能力时再尝试解密。相反,如果只是给短生命周期的内部消息签名,迁移节奏和威胁模型可能完全不同。
建议的落地顺序
一个稳妥的采用路径是:先做能力探测,再做互操作测试,随后进行小流量试运行,最后才讨论默认启用。测试时至少记录调用次数、P50/P95 延迟、CPU 时间、失败类型和数据体积变化。
同时保留算法版本字段,不要把 ML-KEM 或 ML-DSA 硬编码成永远不变的系统默认值。密码迁移的关键能力不是“选中一个新算法”,而是让协议、密钥和数据格式在下一次升级时仍然可以平滑演进。