新2足球贴士网:以太坊开奖(www.326681.com)_Beosin | 深度剖析零知识证实zk-SNARK破绽:为什么零知识证实系统并非万无一失?
新2足球贴士网(www.ad6868.vip)是国内最权威的足球赛事报道、预测平台。免费提供赛事直播,免费足球贴士,免费足球推介,免费专家贴士,免费足球推荐,最专业的足球心水网。
随着数字资产和区块链手艺的快速生长,数字隐私珍爱和平安性成为了越来越受关注的话题。在这个靠山下,一种名为"零知识证实(Zero-Knowledge Proof)"的手艺正在逐渐崭露头角。
零知识证实手艺可以在不泄露任何信息的情形下证实某些事情的真实性,被普遍应用于珍爱隐私和平安性。其中,基于零知识证实手艺的zk-SNARK近期备受瞩目,成为数字资产和区块链手艺领域的热门话题,但有一些平安问题却往往被我们忽视。
Beosin将陆续推出zk零知识证实平安研究,第一篇,本文将深入探讨zk-SNARK的靠山,深度剖析零知识证实zk-SNARK破绽:输入假名破绽是若何被挖掘出来的?
zk-SNARK(Zero-Knowledge Succinct Non-Interactive Argument of Knowledge)是一种基于零知识证实的手艺,可以在不泄露真实信息的情形下证实某个声明的真实性。
它是一种异常高效的零知识证实手艺,可以在异常短的时间内天生和验证证实,同时珍爱隐私和平安性。
零知识证实项目Semaphore上曾经被发现了一个可以导致双花的输入假名破绽,破绽提出者poma给出了两笔乐成的示例生意:
图源:https://github.com/semaphore-protocol/semaphore/issues/16
该破绽影响局限异常广,不止涉及到众多着名zkSNARKs第三方库,连众多DApp项目方也不能幸免,本文最后将枚举出各个项目方详细的破绽代码以及修复方案,我们先对输入假名破绽举行详细先容。
2. 破绽原理
Semaphore项目允许以太坊用户在不透漏其原始身份的情形下,以某个团队成员的身份发送投票等操作,其中所有的团队成员组成了一棵默克尔树,每个成员是一个叶子结点。合约需要团队成员提供一个零知识证实,以证实其身份的正当性。为了防止身份伪造,每个证实只能使用一次,因此合约中会存储已履历证过的证实列表,若是用户提供了使用过的证实,程序就会报错。详细的实现代码如下:
图源:https://github.com/semaphore-protocol/semaphore/blob/602dd57abb43e48f490e92d7091695d717a63915/semaphorejs/contracts/Semaphore.sol#L83
可以看到,上述代码首先挪用 verifyProof 校验零知识证实的正当性,接着通过证实参数nullifiers_hash 校验该证实是否是首次使用,但由于未对 nullifiers_hash 举行完整的正当性检查,使得攻击者可以伪造出多个证实通过校验,实现双花攻击。详细地说,由于合约变量类型uint256能够示意的数值局限远大于零知识证实电路,而此处代码仅思量了 nullifiers_hash 自己是否已被使用,未限制合约中的 nullifiers_hash 的取值局限,使得攻击者行使密码学中的模运算可以伪造多个证实通过合约校验。由于参数的取值局限涉及到一些零知识证实相关的数学知识,而且接纳差其余零知识证实算法对应差其余取值局限,因今后文将详细先容。
首先若是要在以太坊中天生和验证zk-SNARK证实,需要使用 F_p-arithmetic 有限域椭圆曲线电路,其中曲线的一样平常方程如下:
可以发现曲线上的点都市举行一个模p运算,以是电路天生的证实参数s值取值局限为[0,1,…,p-1],然则链上合约的变量类型uint256取值局限为 [0,115792089237316195423570985008687907853269984665640564039457584007913129639935],那么当合约的变量局限大于电路取值局限时,存在下列多个具有相同输出的证实参数值:
综上,只要知道了其中一个正当的证实参数s,uint256局限内的s+np( n = 1,2,…,n)都可以知足验证盘算,于是攻击者在获取到随便验证通过的s,即可组织max(uint256)/p个 s都可以通过校验,详细的攻击流程如下:
上文可知,参数的取值局限由p决议,而差异类型的F_p对应差其余p,需要凭证详细使用的零知识算法确定,如:
EIP-196 中界说的BN254 曲线(也称为 ALT_BN128 曲线) p = 21888242871839275222246405745257275088548364400416034343698204186575808495617
circom2 引入了两个新的素数,即BLS12-381曲线 p = 52435875175126190479447740508185965837690552500527637822603658699938581184513
以ALT_BN128 曲线为例,共计可以天生5个差其余证实参数通过验证,盘算历程如下:
3. 破绽复现
由于Semaphore项目自己代码已经更改,重新部署整个项目较为繁杂,因此我们使用现在常用的零知识证实编译器circom编写PoC复现整个攻击历程。为了利便人人更好的明晰整个流程,这里我们先以circom为例,先容Groth16算法的零知识证实天生和验证历程。
图源:https://docs.circom.io/
1.项目方需要设计一个算术电路并使用 circom 语法将其编写为一个电路形貌文件 *.circom
2.编译电路文件,并将其转化为 R1CS 的电路形貌文件
3.使用snarkjs库凭证输入文件 input.json 盘算出对应的 witness
4.接着通过可信设置天生一个证实密钥 Proving key 和验证密钥 Validation key,其中Proving key用于天生证实Proof, Validation key 用于验证Proof,最后用户行使密钥天生对应的零知识证实Proof
5.验证用户的证实
接下来我们将根据上述流程分步举行先容。
3.1 编写 multiplier2.circom
为了利便人人明晰,我们直接使用circom官方的demo,详细代码如下:
pragma circom 2.0.0;template Multiplier2() { signal input a; signal input b; signal output c; c <== a*b; }
component main = Multiplier2();
该电路中有两个输入信号a和b,一个输出信号c,而且c的值是a和b相乘的效果
3.2 编译电路
使用下列下令行编译multiplier2.circom,并将其转化为R1CS:
circom multiplier2.circom --r1cs --wasm --sym --c
编译后会天生4个文件,其中
•--r1cs:天生的circuit.r1cs是二进制名堂的电路约束文件
•--wasm:天生的multiplier2_js文件夹包罗wasm汇编代码,和天生witness所需的其他文件目录(generate_witness.js、multiplier2.wasm)
•--sym:天生文件夹multiplier2.sym,是一个符号文件,用于调试或以注释模式打印约束系统
•--c:天生文件夹multiplier2_cpp,包罗天生witness所需的c代码文件
,,,,澳5(www.eth0808.vip)是澳洲幸运5彩票官方网站,开放澳洲幸运5彩票会员开户、澳洲幸运5彩票代理开户、澳洲幸运5彩票线上投注、澳洲幸运5实时开奖等服务的平台。www.326681.com采用以太坊区块链高度哈希值作为统计数据,联博以太坊统计数据开源、公平、无任何作弊可能性。联博统计免费提供API接口,支持多语言接入。
注重:天生witness有两种方式,一种是使用wasm,一种是使用刚天生的C++代码,若是是大型电路的话使用C++代码比wasm效率更高
3.3 盘算witness
在multiplier2_js文件夹下确立input.json文件,该文件包罗了以尺度json名堂编写的输入,此时使用字符串而不是数字,是由于js不能准确处置大于2^{53}的数,针对指定的 input.json 天生对应的witness:
node generate_witness.js multiplier2.wasm input.json witness.wtns
3.4 可信设置
该步骤主要是选取零知识证实需要的椭圆曲线类型,以及天生一系列原始密钥*.key文件,其中multiplier2_0000.zkey包罗证实密钥、验证密钥,multiplier2_0001.zkey则是验证密钥,最终导出的验证密钥文件是verification_key.json
snarkjs powersoftau new bn128 12 pot12_0000.ptau -vsnarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -vsnarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -vsnarkjs groth16 setup multiplier2.r1cs pot12_final.ptau multiplier2_0000.zkeysnarkjs zkey contribute multiplier2_0000.zkey multiplier2_0001.zkey --name="1st Contributor Name" -vsnarkjs zkey export verificationkey multiplier2_0001.zkey verification_key.json
3.5 天生证实
行使snarkjs有两种方式可以天生证实,一种是下令行,一种是剧本天生。由于我们需要组织攻击向量,以是这里主要使用剧本天生。
3.5.1 天生正常 publicSignal
snarkjs groth16 prove multiplier2_0001.zkey witness.wtns proof.json public.json
该下令会输出两个文件,其中proof.json是天生的证实文件,public.json是公共输入值。
3.5.2 天生攻击 publicSignal
async function getProof() {
let inputA = "7"
let inputB = "11"
const { proof, publicSignals } = await snarkjs.groth16.fullProve({ a: inputA, b: inputB }, "Multiplier2.wasm", "multiplier2_0001.zkey")
console.log("Proof: ")
console.log(JSON.stringify(proof, null, 1));
let q = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617")
let originalHash = publicSignals
let attackHash = BigInt(originalHash) + q
console.log("originalHash: " + publicSignals)
console.log("attackHash: " + attackHash)
}
天生的证实Proof、原始验证参数originalHash和攻击参数attackHash如下图所示:
3.6 验证证实
证实的验证方式同样也有两种,一种是使用snarkjs库举行验证,一种是合约验证。我们这里主要使用链上合约的验证方式验证原始证实参数originalHash、攻击证实参数attackHash。
这里我们使用snarkjs自动天生一个验证合约verifier.sol,注重最新版本0.6.10的snarkjs天生的合约已经修复了这个问题,以是我们使用旧版本天生合约:
snarkjs zkey export solidityverifier multiplier2_0001.zkey verifier.sol
合约要害代码如下:
function verify(uint[] memory input, Proof memory proof) internal view returns (uint) { VerifyingKey memory vk = verifyingKey(); require(input.length + 1 == vk.IC.length,"verifier-bad-input"); // Compute the linear combination vk_x Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); for (uint i = 0; i < input.length; i++) vk_x = Pairing.addition(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i])); vk_x = Pairing.addition(vk_x, vk.IC[0]); if (!Pairing.pairingProd4( Pairing.negate(proof.A), proof.B, vk.alfa1, vk.beta2, vk_x, vk.gamma2, proof.C, vk.delta2 )) return 1; return 0;}
此时,使用originalHash验证通过:
最后使用刚伪造的attackHash:
21888242871839275222246405745257275088548364400416034343698204186575808495694,同样验证通过!即统一份proof,可以被多次验证通过,即可造成双花攻击。
此外,由于本文使用ALT_BN128 曲线举行复现,因此共计可以天生5个差异参数通过验证:
4. 修复方案
Semaphore 项目已经针对该破绽举行了修复,详细修复代码如下:
图源:https://github.com/semaphore-protocol/semaphore/blob/0cb0ef3514bc35890331379fd16c7be071ada4f6/packages/contracts/contracts/base/SemaphoreVerifier.sol#L42
图源:https://github.com/semaphore-protocol/semaphore/blob/0cb0ef3514bc35890331379fd16c7be071ada4f6/packages/contracts/contracts/base/Pairing.sol#L94
然则该破绽属于实现上的通用破绽,经由我们Beosin平安团队的研究发现,众多着名的零知识证实算法组件和DApp项目都受到该破绽的影响,绝大部门后续举行了实时修复。以下枚举出部门项目方的修复方案:
ethsnarks:
图源 https://github.com/HarryR/ethsnarks/commit/34a3bfb1b0869e1063cc5976728180409cf7ee96
snarkjs:
图源:https://github.com/iden3/snarkjs/commit/25dc1fc6e311f47ba5fa5378bfcc383f15ec74f4
heiswap-dapp:
图源:https://github.com/kendricktan/heiswap-dapp/commit/de022ffc9ffdfa4e6d9a7b51dc555728e25e9ca5#diff-a818b8dfd8f87dea043ed78d2e7c97ed0cda1ca9aed69f9267e520041a037bd5
EY Blockchain:
图源:https://github.com/EYBlockchain/nightfall/pull/96/files
此外,尚有部门项目未能实时修复,Beosin平安团队已与项目方取得联系,正在努力协助修复。
针对此破绽,Beosin平安团队提醒zk项目方,在举行proof验证时,应充实思量算法设计在现实实现时,由于代码语言属性导致的平安风险。同时,强烈建议项目方在项目上线之前,追求专业的平安审计公司举行充实的平安审计,确保项目平安。
查看更多,五湖四海足球吧(www.ad6868.vip)凝集民间高手免费提供各联赛足球资讯、足球推荐、足球贴士等,致力为广大波友提供更全面、更专业的赛前预测分析,让更多球迷随时随地找到自己想要的赛事资讯,以及在本站尽情发言自己的观点。
网友评论