别名攻击
最后更新于
有些ZKP隐私应用需要通过nullifier阻止双花,该nullifier以ZK的形式绑定在proof中,可以被验证者证明,并在相关动作结束后标记为“已使用”,来避免双花。
不过,如果应用实现有问题,这一点可以通过循环群的特性来绕开。
以下是几个例子:
为了减少某些ZKP方案的gas消耗,以太坊为alt_bn128 in 曲线定义了加法和乘法的两个预编译合约。
曲线alt_bn128的定义为:
在有限域F_p
中,基于生成元P1(1,2)
的循环子群的阶为q
。
在循环子群中,有
也即,q
在有限域计算中可以被视为0,对任意相同点加上任意数量的q
都会得到它自己。
由于我们在相关计算中一般使用uint256
,其最大值为M
,那么对于给定的参数A
,有N
个相同结果的别名:
也就是说,如果A
是nullifier,你可以构建至多N
个别名,它们是不同的自然数,但在循环群的运算中会得到相同的结果。因此,防止双花的证明就无效了,甚至可以三花四花五花。
此类型的攻击最初发现于隐私层应用Semaphore中,而其源头可以追溯至2017年Christian Reitwiessner写的一段不安全的样例实现。不幸的是,很多zkSNARKS的库如snarkjs
和ethsnarks
也都遵照了该样例。
解决方案很简单,只需要限制输入值需要小于q
(snark_scalar_field
)。