okx

隐私交易的天堂:链上混币器 Tornado.cash

区块链 安全

作者:laker & 极光 @知道创宇404区块链安全研究团队日期:2021年3月8日

前言

区块链从设计上并不是完全匿名的,充其量是伪匿名的。任何一个人或者组织可以轻而易举的创建一个Hash账户并参与校验,虽然这样的账户不会与个人进行一一对应,但由于交易的公开性、任何人都可以在公共账本上追踪你的交易,并可能利用这些信息找出你的真实身份。

寻求匿名不仅仅是罪犯和有事要隐瞒的人的专利;匿名购买比特币有很多理由。加密货币交易所持有的 know your customer (KYC)数据是黑客攻击的主要目标,包括 Binance 和 Coinsquare 在内的多家交易所近年来都遭到黑客攻击。

什么是零知识证明

零知识证明(Zero—Knowledge Proof) 是由S.Goldwasser、S.Micali及C.Rackoff在20世纪80年代初提出的。它早于区块链诞生,但由于区块链,它被大家所熟知。它指的是证明者能够在不向验证者提供任何有用的信息的情况下,使验证者相信某个论断是正确的

零知识证明可以分为交互式非交互式两种。

  • 交互式

零知识证明协议的基础是交互式的。它要求验证者不断对证明者所拥有的“知识”进行一系列提问。证明者通过回答一系列问题,让验证者相信证明者的确知道这些"知识"。然而,这种简单的方法并不能使人相信证明者和验证者都是真实的,两者可以提前串通,以便证明者可以在不知道答案的情况下依然通过验证。

  • 非交互式

非交互式零知识证明不需要交互过程,避免了串通的可能性,但是可能需要额外的机器和程序来确定实验的顺序。

通俗的来讲,就是既证明了自己想证明的事情,同时透露给验证者的信息为"零"。

比如:用户在系统注册时,系统不会保存用户的密码明文,而是保存了密码的哈希值;用户在登录系统时,只需要输入注册时的密码,系统会根据用户输入密码产生的哈希值与系统数据库保存的哈希值进行比对。如果一致,则系统认为当前登录用户知道该账号的密码

这样,用户不需要告诉网站密码,就能证明自己的身份。这其实就是一种零知识证明。

混币服务tornado.cash

Tornado.cash 可帮助你收回隐私,以隐藏发送地址的方式将 Ether 发送到任何地址。通过零知识证明实现。你可以使用此应用将 ETH 存入非托管智能合约,然后轻松生成凭据来证明你已经执行了存款,但未透露原始地址。而后,取款时应用会将此证明发送给服务商,服务商会将其提交给智能合约,然后智能合约将 ETH 发送给所需的收件人,并向服务商支付少量费用。

在进行存款时,官方会返回凭据,这样你在取出时提供相应的凭据即可进行取出

存入了存款,过了一段时间以后,你便可以通过该note将存款取出,而取出时可以使用一个新的地址,这样,就无法追溯到该笔交易了。

ETH的交易虽然不匿名,因为点对点的传输永远是存在一个可追溯的连接,但是tornado.cash提供了一种任何人都可以向其进行转发相同存款的方式并提供存款凭证,然后在存款者提供存款凭证时转给存款者代币的方式来尝试去掉这个连接。

区块链透明传输环境进行匿名token转移如何实现

在tornado.cash具体实现中采用了Merkle Tree,用户每次存款将会调用insert向Merkle Tree中进行结点插入(存款证明)

function deposit(bytes32 _commitment) external payable nonReentrant {
    require(!commitments[_commitment], "The commitment has been submitted");

    uint32 insertedIndex = _insert(_commitment);//插入树结点
    commitments[_commitment] = true;//证明置为true
    _processDeposit();

    emit Deposit(_commitment, insertedIndex, block.timestamp);
  }
function _insert(bytes32 _leaf) internal returns(uint32 index) {
    uint32 currentIndex = nextIndex;
    require(currentIndex != uint32(2)**levels, "Merkle tree is full. No more leafs can be added");
    nextIndex += 1;
    bytes32 currentLevelHash = _leaf    bytes32 left;
    bytes32 right;

    for (uint32 i = 0; i < levels; i++) {
      if (currentIndex % 2 == 0) {
        left = currentLevelHash;
        right = zeros[i];

        filledSubtrees[i] = currentLevelHash;
      } else {
        left = filledSubtrees[i];
        right = currentLevelHash;
      }

      currentLevelHash = hashLeftRight(left, right);

      currentIndex /= 2;
    }

    currentRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE;
    roots[currentRootIndex] = currentLevelHash    return nextIndex - 1;
  }

最终经过添加Merkle Tree叶子节点后给出一个存款证明。形如

当存款者在取钱的时候,则可以通过提供该凭据进行取出,但是这里不禁有人会问,仿佛没有体现零知识证明?

事实上,在存币时,真正被提供的数据为:

而在取出时取款者提供的数据则通过note进行解密成为如下参数

_proof:存款证明

_root:表示在哪一个Merkle Tree根

_nullifierHash: 代表是否无效化,置为true则该存款已使用

_recipient : 取款时代币接受者的地址

传入数据是根据存款后返回的note进行解密进行填入的,相当于在交易的过程中,你通过存币后返回的的_proof、_root、_nullifierHash 来证明了你的存款,这便是零知识证明的体现。

在代码层面上,如何通过_proof、_root、_nullifierHash证明这笔存款呢?

这里就要关注withdraw函数了:

    function withdraw(bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) external payable nonReentrant {
    require(_fee <= denomination, "Fee exceeds transfer value");
    require(!nullifierHashes[_nullifierHash], "The note has been already spent");
    require(isKnownRoot(_root), "Cannot find your merkle root"); // Make sure to use a recent one
    require(verifier.verifyProof(_proof, [uint256(_root), uint256(_nullifierHash), uint256(_recipient), uint256(_relayer), _fee, _refund]), "Invalid withdraw proof");

    nullifierHashes[_nullifierHash] = true;
    _processWithdraw(_recipient, _relayer, _fee, _refund);
    emit Withdrawal(_recipient, _nullifierHash, _relayer, _fee);
  }

回撤时采用三部分数据,_root表示对应的Merkle Tree,_nullifierHash同时也表达是否该条存款被使用。

在最后的存款验证阶段使用了一个单独的验证器合约,在此地址进行了部署

https://etherscan.io/address/0xce172ce1f20ec0b3728c9965470eaf994a03557a#code

关键函数verifyProof,该函数则是零知识验证的具体实现,载入Proof后将input(uint256(_root), uint256(_nullifierHash), uint256(_recipient), uint256(_relayer), _fee, _refund)依次加载进vk_x并交给Pairing.pairing进行校验,具体代码实现如下:

function verifyProof(
        bytes memory proof,
        uint256[6] memory input// _proof, [uint256(_root), uint256(_nullifierHash), uint256(_recipient), uint256(_relayer), _fee, _refund]
    ) public view returns (bool) {
        uint256[8] memory p = abi.decode(proof, (uint256[8]));

        // Make sure that each element in the proof is less than the prime q
        for (uint8 i = 0; i < p.length; i++) {
            require(p[i] < PRIME_Q, "verifier-proof-element-gte-prime-q");
        }

        Proof memory _proof;// 初始化Proof
        _proof.A = Pairing.G1Point(p[0], p[1]);// 将dp上的Prove赋值
        _proof.B = Pairing.G2Point([p[2], p[3]], [p[4], p[5]]);
        _proof.C = Pairing.G1Point(p[6], p[7]);

        VerifyingKey memory vk = verifyingKey();// 生成vk

        // Compute the linear combination vk_x
        Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0);
        vk_x = Pairing.plus(vk_x, vk.IC[0]);

        // Make sure that every input is less than the snark scalar field
        for (uint256 i = 0; i < input.length; i++) {
            require(input[i] < SNARK_SCALAR_FIELD, "verifier-gte-snark-scalar-field");
            vk_x = Pairing.plus(vk_x, Pairing.scalar_mul(vk.IC[i + 1], input[i]));// 加载进vk_x
        }

        return Pairing.pairing(
            Pairing.negate(_proof.A),
            _proof.B,
            vk.alfa1,
            vk.beta2,
            vk_x,
            vk.gamma2,
            _proof.C,
            vk.delta2
        );
    }

在通过该验证后(确认已存款并且该存款未被取出)则进行取款标志置为true并利用_processWithdraw函数进行资产取出

function _processWithdraw(address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund) internal {
    // sanity checks
    require(msg.value == 0, "Message value is supposed to be zero for ETH instance");
    require(_refund == 0, "Refund value is supposed to be zero for ETH instance");

    (bool success, ) = _recipient.call.value(denomination - _fee)("");
    require(success, "payment to _recipient did not go thru");
    if (_fee > 0) {
      (success, ) = _relayer.call.value(_fee)("");
      require(success, "payment to _relayer did not go thru");
    }
  }

具体算法描述如下

要取出树中位置为 i 的硬币(k,r),用户按以下步骤操作:

智能合约验证了_nullifierHash散列的真实性和唯一性。在验证成功的情况下,它发送(N−f)到指定地址并将h置为true添加到哈希列表中。

nullifierHashes[_nullifierHash] = true;

思考:tornado.cash真的匿名吗

Tornado通过使用智能合约打破地址之间的链上联系来改善交易隐私,该合约接受ETH存款,随后可由不同的地址提取。用户在存款时需要提供秘密的哈希值,之后在提现时提供zkSnark证明,以显示对秘密的了解,而不泄露秘密或之前的存款本身。这样就把提现和存款脱钩了。而是否这样已经达到足够的匿名了呢?显然不是

  • 在存取款的过程中,仍旧应该使用代理等手段隐藏自己的网络层数据等信息,ISP可以记录发送到中继层的数据包的时间戳,并将它们与取款事务时间戳相关联。
  • 存取款时间间隔问题,若存取款时间间隔较短,将可能导致存取款交易发生时间关联,造成匿名性的削减。因此官方建议在存款后过一段时间之后再执行取款操作。

除此之外,在其他混币服务中可能只设计一个回撤合约调用,这里如果需要直接调用合约并且不涉及接收地址的参数传递进行新地址提现则时,要从一个新生成的地址中执行该回撤函数提现交易,那么用户则需要在里面有一些ETH来支付gas。但这个ETH的来源(一般是交易所)会破坏Tornado的隐私。因此,首选的替代方案是再次使用中继器网络。

原本gas的主动支付需要依赖于在KYC后的中心化交易所购买ETH,而替代方案旨在通过将用户的负担转移到中继器上,以减少这种上链用户体验摩擦,其成本由钱包提供商链上/链下和/或用户链下补偿。

总结

零知识证明可以让原本透明的数据(_commitment)进行隐藏和下链(note的不可获取性),但是在下链和上链过程中的隐私安全不被tornado.cash保护,仍需自行做出一些防护。

下链后通过note还原证明数据(_proof, [uint256(_root), uint256(_nullifierHash), uint256(_recipient), uint256(_relayer), _fee, _refund])),该凭据note是恢复你的R(_Root)、h(_nullifierHash)、A(_recipient)、f(费用)、P(_proof)的唯一方式,切不可丢失或遗忘。

最后进行存款的证明并转给一个新的地址,从而中断转账中透明的数据连接的效果。

本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1497/

相关内容

扎实推动高质量发展在湖南农信系统落地生根

洪 樱 成依潇 刘雯娟 黄利飞 新型农业经营主体贷款余额177.2亿元,累计涉农贷款余额达6264.5亿元; 普惠型小微企业贷款余额达2182亿元,支持普惠型小微企业户数50.8万户; 新版手机银行客户数1244万户,收单商户数79万户,线···

全国港口前三季度吞吐量出炉

1-9月,全国港口集装箱吞吐量前10名分别是:上海港(第1)、宁波舟山港(第2)、深圳港(第3)、青岛港(第4)、广州港(第5)、天津港(第6)、厦门港(第7)、苏州港(第8)、北部湾港(第9)、日照港(第10)。图片来源于港口圈1-9月,···

定安打出组合拳推动知名企业纷纷落地

海南日报记者 李豌 特约记者 孙国富蜜雪冰城全球供应链总部基地和全国冷链物流总部基地项目、煌上煌集团……近年来,大企名企纷纷落地定安。国际投资单一窗口综合管理系统数据显示,2020年5月至今年9月,定安县在库项目36个,签约金额达158.9···

45年·45人·45个典型改革案例丨熊维政:一定要把信阳茶油做上市

□本报记者 胡巨成 刘宏冰潜心医药行业40余年,将一家作坊式医药小厂,做成大别山革命老区和全国贴膏剂药业首家上市企业,打造出“百亿级贴膏剂生产基地”的羚锐制药前“掌门人”熊维政,在他60岁时急流勇退,放手交棒,转身创办了信阳信锐油茶股份有限···

山东区划设想,二分滨州,组建渤海市,利津改区,邹平与高青互换

近年来,随着我国产业结构的不断调整,经济增长方式也在持续优化,特别是随着交通等基础设施的完善,区域经济开始朝着一体化发展方向迈进。如果用《射雕英雄传》中的一句话来形容,江苏是“东邪”、广东是“南帝”、四川是“西毒”,那么山东则是“北丐”,此···

为什么河南经济是最没有希望的?上车,带你深度了解河南的问题

“河南小孩出生就是为了离开河南”,这是我最近一个关于河南经济评论文章下点赞最高的评论。这句话我深深刺痛着自己,因为我自己就是河南人,深知这里面包含了多少无奈和心酸。当人们在聊地域之争的话题时,大家都会为自己的省份争辩几句,然而只有河南人,会···

关注双11丨“88VIP”淘宝天猫全网商品都能用花呗分期免息

2023天猫“双11”活动今晚8点正式开始。今年“88VIP”大额券总规模达到200亿,用户可领券额度最高可达860元。支付宝针对“88VIP”淘宝天猫用户还推出花呗分期免息服务,消费者购买大件商品又多了一重实惠。“88VIP”用户购买单价···

每日新闻,60秒知晓世界热点

2023年10月31日,星期二,农历九月十七1、31省份前三季度人均可支配收入公布:上海北京首超6万元位居全国前列,浙江天津江苏同属4万+梯队紧随其后;长三角万亿城市经济三季报:合肥增速第一,宁波增速超上半年;2、工行、农行、中行、建行、邮···

2024年城乡居民参保调整,一次性补缴5.9万,每月能领2300元吗?

随着时间的推移,社会保障制度也在不断地完善和调整。2024年城乡居民参保也将迎来新的一轮调整。据相关政策规定,未来居民参保需要一次性补缴5.9万,每月能领2300元。这个政策引起了很多人的关注和讨论。对于这个政策,有些人认为一次性补缴5.9···

老百姓:第三季度净利润同比增长32.78% “聚焦发展”战略优势凸显

中证网讯(记者 段芳媛)老百姓10月30日晚间披露2023年第三季度报告。公司前三季度实现营业收入160.42亿元,同比增长16.44%;实现归属于上市公司股东的净利润7.17亿元,同比增长17.54%。其中,第三季度实现营业收入52.31···

紧抓机遇开展差异化竞争 骆驼股份积极开拓国际市场

骆驼股份 黄剑波/供图 彭春霞/制图证券时报记者 韩忠楠越来越“卷”的新能源汽车赛道,既充满挑战,也酝酿着新的机遇。近期,受益于华为与赛力斯联合打造的全新问界M7的热销,与之相关的汽车产业链在A股市场的热度也随之升温。这当中,为问界M5/M···

宝山罗店:罗南二村 半年跌幅近乎恐怖 郊区老破小太可怕

前几天,我们写了几个宝山区二手房系列,美兰湖板块的万科琥珀郡园以半年跌幅近五分之一位列榜首,我以为就是跌幅极限。然后,今天现场去看了位于美兰湖南侧的罗南新村,在那周围详细地看了看,然后比较了一下罗南二村最近成交与4月份左右的成交记录,愕然发···

压倒许家印并不是造车,而是恒大童世界,砸几千亿搞了十几个鬼城

恒大集团以其高调的投资和建设项目而闻名,最近引起了人们的广泛关注。与传统地产业务不同,恒大集团的新尝试是在娱乐旅游领域建设恒大童世界。这一巨大的投资计划引发了广泛的争议和讨论。恒大童世界的建设规模之大令人瞩目。据报道,恒大集团计划投资数千亿···

《人民日报》警告奏效?98款,突破1亿台!华为正式宣布

导语:在科技的浪潮中,华为从遭遇“极限施压”,到芯片突破和鸿蒙生态的自研,始终展现出卓越的技术实力和坚韧不拔的创新决心。华为面对挑战:技术封锁与自主创新在2019年,《人民日报》发送《人民日报评华为遭"极限施压":科技自立,时不我待》一文,···

中国钢铁大王戴国芳,入狱5年东山再起,再造500强民企狂赚1957亿

他从一个收废品的穷小子,摇身一变,登上了中国400富豪榜。他的钢铁厂年销售额已超过1个亿,手下员工超过1千人,他就是钢铁大王戴国芳但是这个钢铁界的王者,却因为一时错误,被捕入狱,还坐了5年牢。出狱后,他不忘初心重操旧业,不仅再次创办炼钢厂,···

油价暴跌倒计时,专家透露:11月国内高油价将消失!

随着外资油站的进入,国内加油站市场的竞争格局正在发生重大变化。近日,多位专家在接受记者采访时表示,预计11月国内高油价将不复存在。这一预测的背后,是外资油站的入驻带来的市场冲击和国内油价的持续波动。外资油站的进入,打破了国内加油站的垄断格局···

共话中国经济新机遇丨专访:中国经济展现出发展韧性

新华社日内瓦10月30日电 专访:中国经济展现出发展韧性——访联合国贸发会议资深经济学家梁国勇新华社记者陈斌杰联合国贸发会议资深经济学家梁国勇日前接受新华社记者书面专访时表示,中国经济今年前三个季度的增长态势展现出了发展韧性和潜力。中国国家···

润达医疗:目前在上海、北京等地区部分医疗机构已开展LDT相关业务的试行

润达医疗近期接受投资者调研时称,目前在上海、北京等地区部分医疗机构已开展LDT相关业务的试行,公司在上海等地区积极和相关部分医疗机构展开合作,共同推进LDT相关业务在医疗机构的开展。未来随着相关政策法规进一步完善,LDT相关业务将给公司带来···

国航率先公布第三季度财报,疫情后首度扭亏

在阅读此文之前,希望用您发财的小手点一下“关注”,文章内容来源于网络但是最后会有小编的个人感悟,如有不足之处可以评论指出,谢谢您的支持。民航行业近期公布的积极消息显示了行业的积极向上趋势。多家航空公司在财报中宣布扭亏为盈,旅客运输量也逐步恢···

竹塑革命!中国发改委推动“以竹代塑”三年行动计划。

近日,中国国家发展和改革委员会发布了一份重要通知,名为《加快“以竹代塑”发展三年行动计划》,这一举措旨在推动“以竹代塑”产业体系的快速建立。这个消息将给与竹制品、造纸等行业密切相关的产业带来利好消息。竹子作为中国特色植物,广泛应用于造纸、包···