首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

用一个例子说说零知识证明

先说一些废话。

我是从15年底开始接触区块链的,16年中间的时候正式开始做「原本」,到现在也有3年的时间了。这3年正好经历了国内区块链从无人知晓到遍(yi)地(di)开(ji)花(mao)的一个大波浪,对于区块链的认知也以每个月颠覆一次的速度迭代着。

做为一个搞技术的人,认知的颠覆倒主要都来自于非技术的方面,比如经济激励、比如非中心化信任。从技术的角度看呢,我会觉得和机器学习相比,区块链的技术深度还是很浅,可能还需要一段时间的发展,才会迎来下一个量变引起的质变,支撑起大规模落地的应用。

在17、18年满世界奔走的过程中,也有幸认识了领域内的各路大神。和国内浮躁的环境相比,我也觉得区块链领域真正的技术创新也都还是发生在国外。目前大的突破方向有两个,一个是扩容(或者叫加速),另一个就是私密计算(大家都喜欢叫隐私计算,但是叫隐私计算总感觉是在暴露别人的隐私)。

扩容就是解决区块链的性能问题。以目前几十TPS的性能,根本无法做到大规模应用。解决的思路有两类,链上扩容(比如分片)和链下扩容(闪电网络、Layer 2)。扩容不是这一篇的主题,就不细说了。说到这要偷偷地补一句,Layer 2在全球范围的火热也就是最近半年的事情,而我们其实在17年的时候就已经在设计我们自己的Layer 2方案,并且部署到项目中开始应用了。说到这某个人就觉得特别心酸,因为并没有多少人知道这事,哈哈。

私密计算是解决区块链无法保护隐私的问题。因为区块链上的数据天然是全公开的,任何人都可以查看。假如一个人知道了你的钱包地址,就可以看到你的余额、你所有的转账记录。

当然区块链支持的功能远远不止"转账"这一种。设想一下买保险的场景,买保险需要提供我的体检报告来证明我的健康状况,假如用区块链来实现的话,代表着我的体检报告就要记录到区块链上昭告天下了,我感觉这样子并不是十分妥当。

私密计算就是用来解决这样的问题。私密计算支持在区块链上记录计算结果,用共识完成对于计算结果的验证,而不暴露计算所用到的原始数据。

比如用哈希(Hash)举例子,我可以在区块链上记录一个哈希值,证明我知道这个哈希值的原始数据,但是不暴露这个原始数据。

私密计算上目前在研究的技术主要是安全多方计算(MPC)和零知识证明(zk-SNARKs、zk-STARKs等)。接下来我就以匿名交易作为例子,说一下zk-SNARKs到底是在干什么。

现有的匿名交易的实现主要有三类,使用环签名的比如Monero,使用零知识证明的ZCash,还有最近火起来的使用Mimblewimble协议的Grin等。

Mimblewimble协议比较特殊,链上设计非常简单,但是完成转账需要发送方和接收方之间私下进行一次交互。完成这次交互需要双方见面,或者同时在线,这会导致其应用场景比较受限。

而另外的两种方法在实现保护隐私的思路上是一致的,都是交易记录混合。

我们假设有一个中转地址,所有人都把Token转到这个中转地址,然后再从中转地址转出来。通过技术手段,使得没有人可以把转入的交易记录和转出的交易记录一一对应起来,就实现了交易的匿名。

环签名和零知识证明都是在这个隐藏对应关系的环节起作用。

环签名方法是这样的:我想要转账,我要先等待其他想要转账的人出现,当有足够多的人出现后,我和这些人一起生成一个环签名,一起把Token转入一个中转地址。然后通过证明我的签名在这个环上,把中转地址中我的Token转走。环签名保证了我可以证明我在环上,但没人知道我是环上的哪一个人。

这样我们可以看出来,环签名的问题是显而易见的,转账需要等待其他人一起,并且假如没有足够多的人一起的话,匿名性是不高的。

零知识证明的方法就好很多了,你可以把整个区块链系统想象成一个大的中转地址,所有人都往这个地址里转Token,所有人都从这个地址里把Token转走。不像环签名,这些人之间不需要合作,因此转账随时可以进行,不需要等待。另外整个系统中,历史上所有的交易都被混合在一起,匿名性也要高很多。

那零知识证明是怎样实现转入和转出的分离,并且可以被验证呢?

每个人在转入Token的时候,都自己生成一个数字(不告诉别人),转账的时候在Token上附带一个用这个数字生成的哈希值A,写入区块链系统。

在转出Token的时候,只需要向系统证明:

我知道一个数字,这个数字生成的哈希值是A。

在区块链上大家经过共识,确认这个证明是有效的以后,就允许我把Token转走。因为哈希值A在区块链上,说明转入的Token是确实存在的,而谁有哈希值A背后的数字,说明那个人真的是转入Token的人。

而零知识证明保证了在我整个操作过程中,没有人知道我的数字是什么,也就无法伪装成我把我的Token转走。

那么问题来了,上面的这个证明其实并没有实现转入交易和转出交易的隔离。因为我在转出的时候暴露了哈希值A,其他人通过A就可以找到转入的那笔交易,从而把两笔交易关联起来。

那么我们把证明过程升级一下。因为系统中所有的转入的交易,都会附带一个哈希值,成为了一个哈希值的列表。我的哈希值A也在这个列表中。如果我可以证明:

我知道一个数字,这个数字生成的哈希值在系统的哈希值列表中。

那么我的哈希值A没有暴露,也就没人能把我的转入交易和转出交易关联起来了。

上面红色字体的两句话,就是零知识证明可以做到的事情。当然零知识证明不仅仅可以用来作匿名交易这个事情。比如上面的买保险的例子,同样可以使用零知识证明来实现。

zk-SNARKs是目前相对(仅仅是相对,整体上零知识证明还处于非常早期的阶段,应用场景非常有限)比较成熟的零知识证明方法。关于zk-SNARKs的技术实现,涉及到了很多密码学的方法,在这里就不详细说了,我推荐大家去看ZCash的介绍文章,特别通俗易懂。

https://z.cash/blog/snark-explain/

简单介绍一下,zk-SNARKs方法是这样的,比如拿哈希值来举例子。

首先哈希是一个函数,我们需要先把哈希函数转换成一个代数表达式。哈希函数本身可以就看作一个特别复杂的代数表达式,所以这一步还比较容易。

而对于使用了很多逻辑语句、控制语句的函数,就不是那么容易地变成代数表达式了,这也是目前zk-SNARKs的一个瓶颈。说到这我突然想到,这会不会是函数式编程语言比如Lisp的一个机会呢。

变成代数表达式以后,下一步需要构造一组多项式,使得代数表达式满足条件的一组解,作为这组多项式的系数,使得这组多项式可以互相整除。

这里的核心思想其实是对计算过程的抽样检验,因为是零知识证明,我不知道你原始的数据是什么,那我只能抽查几个点,看看在我抽查的地方,你的计算是不是符合规则的。但是仅仅是对点抽样的话,样本数太少,证明的可信度不高。假如可以把计算过程表示成多项式,那我抽样检查你知不知道这个多项式,就可以通过有限的(和多项式的次数相关,比如一次多项式的话,两个点就够了)抽样得到可信的结果了。

那么接下来抽样开始了。我随机选择几个点,发给你,你计算后给我返回结果,我验证结果正确,OK,你知道原始的数字。

等等,这个过程有点复杂,涉及到了两个人之间的交互。在区块链上只有节点来验证结果,没有人来生成随机的点。采用上面的方法就无法实现自动化的转账了。

那我们把随机的点改成固定的点,提前写在区块链上,就不需要这个交互的过程了。但是问题也来了,如果提前知道了采样的点,即使我没有符合条件的多项式,也可以构造一个“仅仅在采样点符合条件的多项式”。就是我可以伪造证明,转走别人的Token。

这里需要再升级一下,通过同态加密的方法,把采样点隐藏起来,把加密后的点写入区块链,一样可以完成验证,同时还不暴露采样点。这样就形成了最终的zk-SNARKs。

zk-SNARKs目前也还是有很多的问题,随便列两个,比如:

第一步从函数到代数表达式,再到多项式的转换过于复杂,实际操作起来难度太高。

采样点的生成,仍然需要依赖一个可信的操作方。这个操作方知道采样点,可以伪造任何证明。这也是ZCash引入了Trusted Setup的原因。但是这个设置的过程需要在系统初始化的时候完成。如果在以太坊上,我部署了一个新的函数,就没法通过链上的方法完成这个安全的初始化。这也限制了其应用。

而技术的问题最终总会被技术升级所解决。零知识证明为区块链带来的保护隐私的特性,有可能带来区块链的下一个爆发点。

目前我们也在积极探索零知识证明的技术和场景,说不定很快就可以在我们的项目看到实际的应用了。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190120G0SO5800?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券