ERC-7520草案详解:零知识证明zk-SNARK公共输入溢出攻击防护

    零知识证明(Zero-KnowledgeProof,后文简写ZKP)是一种密码学概念,它可以用来证明某个声明的真实性,而无需透露有关该声明的任何具体信息。在零知识证明中,证明者可以向验证者证明某个陈述是正确的,而验证者只会得到一个结果:要么接受该陈述的真实性,要么拒绝它,而无需了解证明的具体细节。什么是零知识证明零知识证明概念可以用一个简单的例子来解释。假设有两个人,一个是证明者和一个是验证者。证明者想向验证者证明自己知道一个秘密的密码,而不泄露密码本身。在传统的方式中,证明者可能会告诉验证者密码是什么,但在零知识证明中,证明者可以使用特殊的协议来向验证者证明他知道密码的正确性,而不泄露密码本身。

    目前常见的零知识证明系统算法包括zk-SNARKs、zk-STARKs、BulletProofs等。ZKP在区块链中的应用在区块链技术中,ZKP有多种应用,例如提升隐私、改善可扩展性和安全性等。以下是ZKP在区块链中的一些关键应用:隐私保护区块链是公共的,这意味着任何人都可以查看链上的所有交易。然而,有时候,用户可能希望保持他们的交易信息保密。ZKP允许用户证明他们拥有足够的资金进行交易,同时不必公开他们的资金总额。这大大增强了用户的隐私保护。

    例如,Zcash是一种使用零知识证明技术的加密货币,它允许用户隐藏交易的发送者、接收者和金额。计算压缩与区块链扩容区块链的可扩展性是一个挑战,尤其是在大规模应用中。ZKP可以用于减轻节点的负担,提高整个系统的可扩展性。通过使用ZKP验证交易的有效性,节点无需查看完整的交易历史记录,从而减少了存储和处理的负担,目前应用最广泛的ZKRollup是一种扩展性解决方案,旨在提高以太坊及其他区块链网络的吞吐量和效率。它结合了Rollup和ZKP技术的优势,提供了高性能的去中心化应用程序(DApps)扩展方案。在传统的以太坊网络上,每个交易都需要被验证和记录在区块链上,这导致了交易处理的延迟和高成本。

    而ZKRollup通过将大量的交易批量处理并压缩为单个区块,ZKP则用于证明批量交易的有效性,从而确保交易的正确性和安全性。身份验证零知识证明可以用于验证用户的身份而无需透露敏感的个人信息。例如,一个人可以使用零知识证明向网络证明他们满足某个特定的年龄要求或拥有某种特定的证书,而无需揭示他们的确切年龄或其他身份信息。去中心化存储:服务器可以向用户证明他们的数据被妥善保存,并且不泄露数据的任何内容。总的来说,区块链的零知识证明在隐私保护、计算压缩与扩容、身份验证、去中心化存储等方面有着广泛的应用。它为区块链技术提供了更多的功能和选择,推动了区块链在不同领域的发展和应用。

    ZKP应用中的双花攻击zk-SNARK(Zero-KnowledgeSuccinctNon-InteractiveArgumentofKnowledge)是一种基于零知识证明的技术,可以在不泄露真实信息的情况下证明某个声明的真实性。它是一种非常高效的零知识证明技术,可以在非常短的时间内生成和验证证明,同时保护隐私和安全性,所以应用非常广泛。但是,伴随着应用的扩展,其安全性也越来越受到关注。我们在不久前就曾发现了其通用漏洞:ZKP项目中如果未正确校验verify函数中参数input的取值范围,攻击者可以伪造多个input通过校验,造成双花攻击。这种攻击影响范围非常广,涉及多个zk-SNARK算法包括:groth16、plonk等,并且solidity、js等多种开发语言均存在该漏洞。该漏洞最开始由poma在零知识证明项目Semaphore上首次发现,并给出了两笔成功实施的交易示例,具体如下图所示:https://github.com/semaphore-protocol/semaphore/issues/16该漏洞具体的攻击原理是,如果要在以太坊中生成和验证zk-SNARK证明,需要使用F_p-arithmetic有限域椭圆曲线电路,其中p值用于确定椭圆曲线有限域的范围,所以电路的input取值范围为[0,1,…,p-1]。不同的曲线拥有不同的p值:EIP-196中定义的BN254曲线(也称为ALT_BN128曲线):p=21888242871839275222246405745257275088548364400416034343698204186575808495617circom2引入了两个新的素数,即BLS12-381曲线:p=52435875175126190479447740508185965837690552500527637822603658699938581184513以及plonk2:18446744069414584321随后Semaphore方确认并修复了该漏洞,ZoKrates、snarkjs等zk库也同步进行了紧急修复,但Beosin安全研究员发现该问题目前并未存在一个统一的解决方案,例如Semephore协议将约束写到pairing库中并未在外层业务逻辑中显式校验数据的有效范围;而circom生成的合约代码以及Tornado.Cash则在verify函数中显式地校验SNARK_SCALAR_FIELD,这种混乱不统一的解决方式可能会对很多新的zkDApp项目方造成困扰并出现安全隐患,因此我们希望能够使用一种标准化的方式来解决这个问题。ERC-1922中的双花攻击目前以太坊具有一个zk相关的标准EIP-1922,该标准介绍了用于验证zk-SNARK的Verify合约标准接口,具体代码如下:pragmasolidity^0.5.6;///@titleEIP-XXXXzk-SNARKVerifierStandard///@devSeehttps://github.com/EYBlockchain/zksnark-verifier-standard///Note:theERC-165identifierforthisinterfaceis0xXXXXXXXX.///⚠️TODO:CalculateinterfaceidentifierinterfaceERC1922/*isERC165*/{///@noticeCheckstheargumentsofProof,throughellipticcurve///pairingfunctions.///@dev///MUSTreturn`true`ifProofpassesallchecks(i.e.theProofis///valid).///MUSTreturn`false`iftheProofdoesnotpassallchecks(i.e.ifthe///Proofisinvalid).///@paramproofAzk-SNARK.///@paraminputsPublicinputswhichaccompanyProof.///@paramverificationKeyIdAuniqueidentifier(knowntothisverifier///contract)fortheVerificationKeytowhichProofcorresponds.///@returnresultTheresultoftheverificationcalculation.True///ifProofisvalid;falseotherwise.functionverify(uint256[]calldataproof,uint256[]calldatainputs,bytes32verificationKeyId)externalreturns(boolresult);}其中,零知识证明proof、inputs变量类型都为uint256[],该变量类型是目前ZKP算法中椭圆曲线运算最常用的,但是该接口中也未增加对应的安全防护,因此同样存在双花攻击的巨大安全隐患。ERC-7520解决方案Beosin根据上述问题,提出了EIP-7520防范这种安全风险,具体为以太坊生态中所有使用了zk技术的DApp项目方在compliantverifiercontract中,都必须实现该接口从而使用规范统一而又安全的方式对所有input进行有效范围校验,具体接口如下:pragmasolidity^0.5.6;///@titleEIP-XXXXzk-SNARKpublicinputsVerifierStandard///Note:theERC-165identifierforthisinterfaceis0xXXXXXXXX.///⚠️TODO:CalculateinterfaceidentifierinterfaceEIP7520/*isERC165&ERC1922*/{///@noticeCheckstheargumentsofInputsarewithinthescalarfield///@dev///MUSTreturn`true`ifInputspassesrangecheck(i.e.theInputsare///valid).///MUSTreturn`false`iftheInputsdoesnotpassrangecheck(i.e.ifthe///Inputsareinvalid).///@paraminputsPublicinputswhichaccompanyProof.///@parampPublicinputwhichaccompanythecurve.functionverifyPublicInput(uint256[]inputs,uint256p)externalreturns(boolresult);}verifyPublicInput函数是这个标准的核心,涉及到的参数具体含义如下:inputs定义为uint256[]类型,代表了ZKP项目中verify函数涉及到的公共信号参数p定义为uint256类型,该值对应算法中使用的椭圆曲线的p值下面将对比实现与未实现EIP-7520接口的两种情况下,针对该该攻击的不同表现,以向各位项目方表明风险:1假设我们在不调用本eip接口verifyPublicInput的情况下,直接使用verify合约代码进行证明验证,具体代码如下:functionverify(uint[]memoryinput,Proofmemoryproof)internalviewreturns(uint){VerifyingKeymemoryvk=verifyingKey();require(input.length+1==vk.IC.length,"verifier-bad-input");//Computethelinearcombinationvk_xPairing.G1Pointmemoryvk_x=Pairing.G1Point(0,0);for(uinti=0;i

Pixel Artist Pixel Artist
Happy Kittens Puzzle Happy Kittens Puzzle
Penguin Cafe Penguin Cafe
Animal Connection Animal Connection
Snakes N Ladders Snakes N Ladders
Pixel Skate Pixel Skate
BeeLine BeeLine
Draw Parking Draw Parking
Draw Racing Draw Racing
Soccer Balls Soccer Balls
Happy Fishing Happy Fishing
Crashy Cat Crashy Cat

FREE GAMES FOR KIDS ONLINE