首页 网络安全 正文

Plonky3 Fiat-Shamir挑战绑定CVE-2026-46654

摘要

栋科技漏洞库关注到 Plonky3 中存在的 Fiat-Shamir 挑战绑定漏洞,该漏洞现在已经被追踪为CVE-2026-46654,CVSS 4.0评分为8.9。

Plonky3是Polygon(原 Polygon Zero)于 2024 年推出的模块化、高性能、透明的 ZK 证明系统工具包,是Plonky2的全面重构升级版。

一、基本情况

Plonky3 是当前最先进的 ZK 证明工具包,以模块化、高性能、透明安全为核心,兼顾速度、灵活性与抗量子能力,采用了分层模块化。

Plonky3 不仅是 Plonky2 的升级,更是 ZK 技术的范式转变,该产品极大降低了 ZK 开发门槛,推动 zkVM/zkEVM 等技术大规模落地。

Plonky3 Fiat-Shamir挑战绑定CVE-2026-46654

Plonky3 是 Rust 编写的多项式 IOPs(PIOPs)工具包,用于构建零知识证明系统,强调最小预设、高度可组合,可自由定制证明栈。

栋科技漏洞库关注到 Plonky3 中存在的 Fiat-Shamir 挑战绑定漏洞,该漏洞现在已经被追踪为CVE-2026-46654,CVSS 4.0评分为8.9。

二、漏洞分析

CVE-2026-4665高危安全漏洞存在于文件路径 challenger/src/multi_field_challenger.rs以及函数 MultiField32Challenger::duplexing 中。

影响challenger/src/multi_field_challenger.rs和field/src/helpers.rs,源于挑战者组件在生成Fiat-Shamir挑战时未能正确绑定转录本状态。

通过控制证明者一侧的观察值可构造不同转录本生成相同挑战,破坏 Fiat-Shamir 的绑定属性导致证明系统声音性受损,可能伪造成功。

违反不变量:

Fiat-Shamir海绵函数必须将挑战值与观测域元素的完整序列进行强绑定。具体要求如下:

(1)吸收过程必须是单射性:不同的观测序列必须生成不同的海绵状态;

(2) 输出过程具备单射性:速率区中不同的基域单元,必须生成不同的目标域挑战值序列;

(3)每一个被吸收的基域元素,其所有比特位都必须对海绵状态产生影响。

修复版本中通过为所有挑战者类型新增 CanFinalizeDigest trait 和 finalize 方法,在提取摘要前强制执行一次最终状态转换,

确保所有观察值都被纳入摘要计算,切断不同转录本产生相同挑战的因果链。

三、POC概念验证

(一)利用场景

攻击者若能操控证明方的观测数据,即可构造出内容不同但最终生成相同挑战值的证明文本,破坏 Fiat-Shamir 机制的绑定特性。

(二)该漏洞包含三类独立攻击路径

1、分块别名问题(吸收阶段)

duplexing函数通过reduce_32(以 $2^{32}$ 为基数)对输入缓冲区按指定域元素数量分块处理,

既未添加长度标识,也未清空速率区未使用的槽位。

由于reduce_32会将缺失的高位分段与补零分段视作等价内容,

因此先观测数据 $[x]$ 再采样,和先观测补零至指定元素数量的 $[x, 0, \dots, 0]$ 再采样,最终得到的海绵状态完全一致。

攻击者可随意延长或截断观测数据批次的尾部,且不会改变后续生成的挑战值。

2、输出过程非单射问题(输出阶段)

split_32函数将每个基域速率区单元拆分为以 $2^{64}$ 为基数的分段,再通过TF::from_u64转换为目标域元素,

该转换会对数值取目标域阶数(约 $2^{31}$)的模。

若两个不同的基域数值,其 $2^{64}$ 进制分段仅高33位存在差异,二者将生成完全相同的目标域挑战值序列。

这会降低挑战值的有效熵值,若攻击者可在数据输出前篡改海绵状态,还能实现定向伪造。

3、高位截断问题(哈希/默克尔根观测阶段)

通过公式num_f_elms = PF::bits() / 64计算单个基域元素对应的目标域分段数量。

以254比特的BN254域为例,计算得出3个分段,仅覆盖192比特,哈希值每个字的最高62比特会被直接丢弃。

可构造两份仅在第192至253比特存在差异的BN254哈希摘要,交替使用这两份摘要作为观测数据,且不会对最终挑战值造成任何影响。

(三)漏洞佐证

duplexing函数中,

吸收链路采用基数为 $2^{32}$ 的reduce_32,输出链路采用基数为 $2^{64}$ 的split_32,二者进制不兼容且未做长度域隔离。

reduce_32仅通过霍纳法则执行累加运算acc * 2^32 + 分段值,无补零规则与标识位,尾部补零不会改变运算结果;

split_32提取64位分段后通过类型转换与模运算截断高位;

而对于比特宽度非64整数倍的域,PF::bits() / 64向下取整的计算方式,会直接舍弃超出部分的所有比特。

四、影响范围

Plonky3 < 0.4.3

Plonky3 < 0.5.3

五、修复建议

Plonky3 ≥ 0.4.3

Plonky3 ≥ 0.5.3

六、参考链接

管理员已设置登录后刷新可查看



扫描二维码,在手机上阅读
评论
更换验证码
友情链接