早上,我朋友Appi Lab的许多朋友发表了一篇有关“输入假名”的文章。 zkSNARK的攻击。我快速看了一下,感觉很棒。这种攻击的原理实际上相对简单,但是对于不了解zkSNARK及其使用场景的朋友来说,发现和理解它确实很困难。本文讨论了我对这种攻击的分析和理解。这种攻击类型自三天前开始潜伏,至今尚未发现。直到三天前:俄罗斯开发人员poma,在项目信号量中提交了一个问题,并披露了这种攻击方法。博马还在kovan测试网络上验证了这种攻击方法。让我们从信号量项目的代码开始:换句话说,信号量是一个非常有趣的项目,它提供了一组方法,这些方法允许用户广播消息而不显示其身份。我现在不会深入介绍该项目的内容,仅看一下功能即可。 broadcastSignal函数提交证明某个用户发送了特定消息(信号)的证据。只有特定的广播公司(服务器)会调用此功能。信号-广播消息a / b / c的内容和输入-是zkSNARK的证明以及公共信息(声明信息)功能的实现(第82行)。调用verifyProof函数以验证证明以及语句信息是否合理。在第83行,检查是否已使用nullifier_hash。什么是零化器?熟悉ZCash的朋友可能熟悉Nullifier。为了保护交易的私密性,只有对应于Note和Nullifier的哈希信息被存储在链上。 Note表示可以消费的钱,Nullifier表示已经消耗了一定数量的钱。 Note和Nullifier之间存在一一对应的关系。音符只有一个消音器。通过zkSNARK生成证书,以证明Note和Nullifier的正确性以及特定连接的存在。在链上,为了防止重复支出,在执行交易时,有必要确定是否已消耗票据。确定的方法是记录与Nullifier对应的哈希信息。 verifyProof的计算verifyProof的功能在snarkjs项目的template / verifier_groth.sol中实现(以Groth16为例)。 verifyProof只是一个简单的包装,实际的计算是verify函数。验证是验证Groth16的验证公式是否有效,然后查看Groth16的验证公式:输入橙色部分,蓝色部分为vk.IC。 scalar_mul是“标量乘法”。椭圆曲线的计算。 vk.IC是椭圆曲线上的一个点(假设P),输入是标量(假设x)。 scalar_mul(P,x)表示为xP。如果椭圆曲线的阶数为q,则以下等式成立:(x + q)P = xP + qP = xP也就是说,如果使用x + p和x作为输入,则scalar_mul的计算结果相等。换句话说,Groth16的方程式仍然成立。怎么进攻?在智能合约中,输入输入由uint表示。 bn254的曲线通常在以太坊上使用,并且q为:21888242871839275222246405745257275088548400400034034343698204186575808495617。尽管此q相对较大,但uint的最大值仍远大于q。形成攻击方法:用户提交证书和公共输入信息后,攻击者可以修改输入中的nullifier_hash。尽管在逻辑上花费的金额相同,但智能合约认为它要花费不同的费用。智能合约认为一个Note只能对应一个Nullfier。实际上,在这种情况下,一个Note对应于多个Nullfier。如何解决?修复的方法很多,目前最简单的修复方法是在验证功能中添加一个限制:限制输入不能超过q。简介:三天前,俄罗斯开发人员poma公开了一种在zkSNARK应用程序模型下的攻击方法。攻击不需要重新生成证明信息,而仅需要修改与Statement中的Nullfier对应的哈希数据。原理是椭圆曲线是一个循环群,当将输入标量添加到椭圆曲线的阶上时,scalarMul计算结果相等。