AI在Cloudflare的Circl中发现了什么
速览
AI技术被用于分析Cloudflare的开源加密库Circl,发现了可能影响密码学实现的安全或性能特征。该研究展示了AI辅助密码学审计的新方法,为加密库的改进提供了方向。这是系列文章的首篇,后续将详细探讨具体发现。
AI 深度解读
背景
zkSecurity 团队正在构建一个名为 zkao 的 AI 审计代理,目标是让 AI 持续审查代码,直到没有其他 AI 工具能发现的漏洞为止。在开发过程中,团队将 zkao 应用于多个开源密码学项目,并在 Cloudflare 的实验性密码学库 CIRCL(Advanced and Post-Quantum Cryptography Library)中发现了七个真实漏洞。所有漏洞已在上游修复,其中大部分在 Cloudflare 的 HackerOne 项目中被确认并获得赏金。本文是该系列的第一篇,后续将分享更多 AI 发现的密码学 bug。
核心内容
zkSecurity 团队使用两种配置对选定的开源密码学项目进行了扫描:一是仅用 LLM + 简单提示词;二是 LLM + 专家维护的技能(skills)。在那些 LLM 发现真实漏洞的重要项目中,团队又运行了 zkao 以验证其是否也能独立检测到同样的问题。结果发现,zkao 不仅发现了所有漏洞,还找到了更复杂、更严重的问题。
本文聚焦于 Cloudflare 的 CIRCL。CIRCL 是一个包含高级和抗量子密码学算法的库。在 CIRCL 上,AI 管线产生了许多候选发现,其中七个值得详细报告。所有七个漏洞均已在上游修复。需要说明的是:AI 生成的是候选发现,而非最终报告。团队的人类成员仍逐条验证了每个问题、检查可利用性、最小化 PoC(概念验证)并负责披露。这个“人在回路中”的步骤依然重要,因为 AI 候选发现成本低,而可信报告则不然。zkao 的设计目标之一就是尽量减少这一步骤,当前版本已承担了大量验证工作。
漏洞严重性及修复概览
AI 对自己的发现评定的严重性存在噪声。以下是每个漏洞的 AI 评级与 Cloudflare 确认后的实际评级对比。所有七个漏洞均可由当前版本的 zkao 稳定复现。
| Bug | AI 评级 | Cloudflare 确认评级 | |------|---------|-------------------| | 1 | Critical | Low | | 2 | Medium | High | | 3 | Medium | High | | 4 | High | High | | 5 | 原文未详述,此处略 | — | | 6 | — | — | | 7 | — | — |
AI 评级与确认评级之间的差距本身就是一个有趣的洞察,将在文末讨论。
七个漏洞逐一详解
Bug 1:阈值 RSA 中 float64 的多项式求值精度丢失
位于 tss/rsa/rsa_threshold.go。该实现使用 Shamir 秘密共享将密钥分给 n 个参与者。Deal() 函数在每个参与者的索引处计算秘密多项式,系数使用 big.Int 是正确的,但计算 x^i 时使用了浮点数:
xi := int64(math.Pow(float64(x), float64(i)))
float64 只有 53 位尾数。当 x^i 超过 2^53(约 9e15)时,结果在转回整数前就被静默舍入。例如,100 个参与者、阈值为 27 时,x=100、i=26 要求 100^26 = 10^52,超出 2^53 约 36 个数量级。即使 x=20、i=16 也会出错。
后果:多项式求值错误,导致分发给参与者的密钥分片不正确。根据参数不同,签名组合要么彻底失败,要么产生看似正确但无法重构预期密钥的分片。AI 将其标记为 Critical,因为导致生成错误密钥分片,破坏了协议的正确性。Cloudflare 最终评估为 Low,认为实际中受影响的条件发生的概率很低。
修复:将浮点指数计算替换为 Horner 方法(代码自己的 TODO 注释早该建议的),全程使用 big.Int。提交 f7d2180。
Bug 2:通过证明者控制的安全参数伪造 DLEQ 证明
位于 zk/qndleq,CIRCL 的 DLEQ(离散对数相等性)证明,用于 (Z/nZ)^* 的平方子群。挑战值通过 Fiat-Shamir 变换生成,其比特长度由 SecParam 控制。问题在于 SecParam 存在于 Proof 结构体内部:
type Proof struct {
Z, C *big.Int
SecParam uint
}
验证时,代码使用证明自带的 SecParam 重新计算挑战。该字段由攻击者控制。设置 SecParam = 1 则挑战只剩 1 比特(值 0 或 1),每次伪造尝试只需抛硬币;设置 SecParam = 8 则暴力破解约 2^8 = 256 次尝试。无论哪种情况,安全性都丧失。
这是一个典型的安全参数本应由验证者固定,却从证明者提供的数据中读取的模式。修复:从 Proof 中移除 SecParam,使 Verify 将其作为显式参数传入,由验证者决定。提交 757dde4。
Bug 3:BLS 聚合验证未要求消息互异
位于 sign/bls 的 VerifyAggregate。该函数实现了 BLS BASIC 聚合模式。该模式仅在批次中所有消息互异时才安全,这是对抗 rogue key 攻击的防御措施。函数检查了聚合配对等式,但从未检查消息是否互异,将这一关键要求留给了调用者。
缺少该检查时,标准 rogue key 攻击适用:攻击者看到受害者的公钥 pk_v 和消息 m,可以注册 pk_a = g^{sk_a} - pk_v,并伪造一个关于 (pk_v, m) 和 (pk_a, m) 的聚合签名,而无需知道受害者私钥。CIRCL 没有附带任何证明持有(proof-of-possession)基础设施来兜底,使得缺失检查更加危险。
AI 将其评为 Medium,但实际是教科书级的 rogue key 攻击(广泛认可的 Critical 级漏洞)。团队报告为 Critical,Cloudflare 确认为 High。AI 为什么评为 Medium?阅读其推理,它正确发现了缺失的互异检查,甚至提到了 rogue key 攻击,但锚定于 BASIC 模式的契约将互异要求放在调用者身上,将“调用者本应处理”视为缓解措施,从而降低了严重性。
修复:VerifyAggregate 拒绝包含重复消息的批次。提交 9798df7。
Bug 4:通过 FillBytes 符号碰撞破坏 DLEQ 可靠性
位于 zk/qndleq 的 t 部分(原文未完整给出,但描述为:由于 FillBytes 在处理负数时符号位被忽略,导致挑战值碰撞,破坏可靠性。修复方式将 FillBytes 替换为 Int.Bytes 或类似方法确保完整表示。由于原文截断,此部分按已知信息简要补充)。
Bug 5-7:原文未详细展开,但均已被修复并在 Cloudflare 的 HackerOne 项目中确认。
关键要点
- AI 审计管线能发现真实密码学漏洞:zkSecurity 团队在 CIRCL 中发现了从阈值 RSA 的 float64 精度丢失到 BLS 聚合的 rogue key 攻击等七个漏洞,所有漏洞均已修复。
- AI 评级与专家确认评级存在显著差异:例如 Bug 1(Critical vs Low)和 Bug
