硬核!360高级安全专家彭峙酿以Zcash为例,谈零知识性证明的安全和隐私问题

硬核!360高级安全专家彭峙酿以Zcash为例,谈零知识性证明的安全和隐私问题

10月12日,由中国计算机学会(CCF)主办的“2019 CCF区块链技术大会”在成都举行。360高级安全专家彭峙酿博士以《零知识证明在区块链应用中的安全和隐私问题》为题进行了分享,内容非常硬核。
以下是彭峙酿博士分享内容全文,由巴比特整理发布。

比特币的隐私问题



比特币是去中心化数字货币,广播交易到公开账本,防止双花。比特币不存在匿名性,个人交易记录、账户余额以及商家现金流都可能被追踪到,这可能就产生了隐私问题,也会产生钱的等价性问题。人们都希望货币是等价的,但比特币的历史信息可以被查到,某一些可能曾经是黑钱,或者某一些有更高的收藏价值,从而造成比特币并不等价。为了解决这两个问题,人们希望把隐私引入到比特币当中。


比特币交易如图所示,如果想要对公开历史交易信息增加隐私保护,最简单的思路就是把所有东西都加密,比如交易发送者、接收者,以及交易金额,这样就能得到一个隐私的交易。但这里存在一个问题,如果这些数据加密的话,全网其他用户可能没法解密数据,这就跟比特币或者是区块链公开可审计性存在冲突。因此,学者们提出用零知识证明来解决这个问题。


简单介绍一下零知识证明,有一个证明者和一个验证者,以及一个要证明的论述。证明者有一个证据W,证明论述X属于某个语言R。证明者要向验证者证明论述X过程中,会通过一些交互。交互得最后,证明者要向验证者发送一个证明,验证者决定接受或者拒绝该论述。
零知识证明要满足以下这些性质:
完备性:如果论述正确证明者可以说服论述者;
正确性:如果论述错误证明者没办法说服论述者;
零知识性:验证者除了论述是正确的之外,无法获得任何其他信息。
我们往往很难要求证明者和论述者同时在线,所以实际应用中非交互式零知识证明(NIZK)更有价值。在非交互式零知识证明中:证明者发一个π给验证者,验证者可以直接验证得出结论,无需进行交互。对于NIZK,有一个简单的结论,如果因式分解是困难的,对于任意的NP语言都存在非交互式的零知识证明。


有了零知识证明后,我要在区块链上引入隐私就很简单了。我把所有交易全部加密,加密之后我会增加一个证明,证明这笔交易是合法的,所谓的合法就是满足区块链交易的规则,我这个用户确实有这么多钱,而且交易中得钱没有被双花。这样可以解决加密和公开可验证性的冲突。


通用性零知识证明方案性能通常不高,区块链对交易性能又有很强的要求。实际应用中zkSNARKS被大家喜爱,它有额外性能优势。
如图所示为zkSNARKS的流程,参数生成过程中会生成两个密钥,一个是证明密钥PK,一个是验证密钥VK,证明拿到PK有一个W,用PK可以产生证据π,把论述和π发给验证者,验证者用VK可以直接验证这笔交易。


关于zkSNARKS在区块链上的应用,我画了这个图,有一个具体待验证的问题,比如要验证这笔交易是不是合法。该问题可以被等价转化为QAP问题。然后公链项目方可以具体生成公链参数,参数其实就是验证密钥VK和证明密钥PK。我对普通用户要发送一笔交易,首先把交易加密为:C1、C2、C3(实际上是一种编码),同时使用证明密钥PK证明这笔交易合法,得到一个证明π,把交易和证明π一起发上网络,全网用户就可以使用验证密钥VK验证这笔交易得合法性了。这是zkSNARKS在区块链上应用的应用流程。


目前零知识证明在区块链中得应用全景图是非常大的,有各种各样的应用,我们在网上可以看到各种各样的项目,这是项目总体图。
上面讲了为什么要用零知识证明,接下来讲讲零知识证明在区块链应用中的安全和隐私问题。很多项目存在安全问题,我会从以下几个方面做一些总结。

一、实现漏洞

讲到安全,首先是实现漏洞,零知识证明在实现方面的漏洞归纳为三方面:
1、 内存破坏漏洞:现在很多密码学项目使用内存安全语言研发的,主要用rust、java、go,内存破坏问题相对比较少。也有比如LibSNARKS这些项目使用c++编写,但该场景中,内存破坏相关漏洞难以利用,一般只能造成节点崩溃。所以内存破坏问题并不严重。
2、逻辑漏洞:主要是电路设计问题和应用层逻辑问题。
3、密码实现漏洞:零知识证明方案比较新,新的密码方案实现很可能会出现一些新的问题。
首先是电路设计问题。零知识证明在区块链上电路设计上有一个特点,电路设计通常非常复杂,有大量密码实现,有很多约束,又要优化性能,需要有高超的技巧。


我们以Zcash为例看屏蔽交易。这里是zcash屏蔽交易的输入、输出,还有绑定签名,要把一个交易的输入、输出绑定起来。



这是输出电路和输入电路图,总的来讲,这些电路非常复杂,时间问题,这里不细致描述它。如果你看zcash的标准文档,对屏蔽交易描述有上百页文档。
电路常见问题分为3种,一个是电路设计漏洞, Zcash曾经就产生过 faerie Gold攻击,攻击者可选择相同的RHO,造成接收者无法使用收到的钱。门罗币之前也产生过类似的问题。
二是电路与非电路实现不一致的问题,区块链项目最终目标是要保证所有节点都要一致,产生不一致问题就会产生很严重的风险,比如分叉和双花的问题。在使用zkSNARKs的时候,我需要把某一个验证逻辑的C++或者其他高级语言实现,同时我也需要用零知识证明语法实现一次,这两类实现很可能产生不一致的现象,不过在审计中,没有发现知名项目中有这样的问题。这些项目中有非常多的测试代码解决这个问题,很显然他们也意识到了这个风险。
三是标准与实现不一致的问题,Zcash标准有一百多页文档,标准与实现有很多不一致的地方,这可能带来额外的安全风险。我们发现在他的标准文档存在一些安全问题问题,但是在实际审计项目代码审计的过程中没有发现这个问题。但这种不一致性提供了额外的安全风险和攻击面。
其次是应用逻辑问题。应用开发者会调用零知识证明库来实现ZKP应用,但是开发者通常对底层ZKP缺乏足够理解,写代码时很容易产生安全漏洞。


这里网上开源项目semaphore的一个双花问题,它的问题是应该本来有一个唯一的值带入到电路中,但是项目没有限定Nullifier长度,如果该加一个P或者2P都可以使电路满足。这样的花同一个证据可以被使用多次,也就是说同样货币可以被使用多次,从而造成双花问题。


Tron今年实际上也完成了匿名货币的研发。在tron的研发过程中,我以社区贡献者帮忙审计了一些安全问题。这我在tron开发中过程中发现的与semaphore双花漏洞类似的问题。Tron使用了Librustzcash库来对匿名交易进行验证,但没有对带入的参数进行长度和内容上的限制,会产生上述所说的双花问题。


类似的,tron也出现过没有验证一笔交易当中多个输入的Nullifier是否不同,造成双花问题。但这些都是开发最初期出现的问题,基本上马上就得到了修复。
在是密码实现安全问题。新的密码方案的实现,往往会带来一些额外的风险,包括现在比较有名的项目,LibSNARK在2015年就发现项目实现中R1CS到QAP的规约漏洞。LibSNARK实现中没有满足QAP中多项式线性独立的要求,这样就造成soundness可能不满足,解决项目就是增加冗余,这是一篇相关的论文。 (https://eprint.iacr.org/2015/437.pdf
上个月斯坦福大学发现Zcash的Ping攻击和Reject攻击漏洞,他们发现一个节点在区块链网络当中,处理与自身相关的交易时,解密时会产生额外的信息泄露,这样攻击者可以发送恶意伪造恶意交易来判断某一个地址属于哪一个节点。这样打破zcash的不可关联性,相关论文也放在这里。 (https://crypto.stanford.edu/timings/pingreject.pdf

二、信任风险


zkSNARKS有一个基本思路,为什么能够实现高性能呢?提前生成验证者挑战X,保留加密的X,丢弃明文X,大家可以用加密挑战验证整个证明。整个验证过程就是要满足上面的等式。如果攻击者知道X,比如它是项目参数的生成者,它可以绕过所有困难问题直接构造任意证明。这样的后门不会被别人发现,因为伪造的证明也具有零知识性的,所以有没有攻击者利用这个漏洞去创造一些额外的货币,没有人能知道。


解决信任问题的方法,就是使用安全多方计算MPC生成加密X,大家也是这样做的。这里举了一个zcash的例子,他们有专门参数生成的步骤,分成两步,第一步是生成加密的X。这个加密X也可以给其他项目使用。Zcash把所有MPC协议通讯过程全部公开,实现代码也公开,每个参与人会把自己收到什么消息,发出去的消息全部签名放到网络上。这样得话,只要其中一个参与者诚实,我们就可以认为MPC结果是安全的。


第二步是针对具体电路生成参数,第一步和第二步缺一不可。有一些项目直接拿了power of tau的参数来使用,但没有对第二阶段的参数生成进行MPC,这样的项目也是不可信的。
讲讲我对MPC问题的看法,现在很多的项目,以太坊等等都在进行自己的MPC,生成零知识证明参数。但是也有一些项目,没有进行可信的setup。我可以讲下我参与MPC的经历,9月初以太坊有联系到我,说项目方会找一些社区成员参加参数生成的仪式,9月初找到我说把我排到第14个,到时会联系我,但是到现在十月中完全没有任何音讯和消息。虽然MPC方案是安全的,但整个过程不像互联网聊天室一样,你像加入就可以直接加入。谁是第几个人,什么时候到你,完全由项目方来控制,如果你没有自己参与MPC,就不能够百分之百确定这个MPC是安全的。


举一个例子,ZoKrates是零知识证明智能合约编译器,你有一个逻辑想验证,你可以用他把这个验证逻辑编译器为以太坊上零知识验证合约。但这里有一个问题,整个参数生成过程,由合约生成方来控制。如果合约生成方是恶意的,他其实可以伪造任意证明。

三、非屏蔽交易信息泄露


我用爬虫统计了9月Zcash的交易数据,85%数据都是透明交易,没有任何加密,有14%部分屏蔽,半透明,只有1%是完全屏蔽交易,可以说大多数交易都可以追踪。


另外我也统计了一下zcash当前的一下货币池,95%是透明,只有大约5%在屏蔽池。
实际上针对这个问题,很多学者已经在论文中分析了这些匿名货币的可连接性和匿名性。大多数的交易都是可以被追溯的。比如我有一个地址A打了一笔钱给屏蔽池,B打了一笔钱给屏蔽池,这两笔钱总合在一天后从屏蔽池打给了 C,我们可以从交易模式判断出ABC是关联,钱就是A、B要打给C的。用户使用相关、相关的地址、相关的金额、相关时间都可以拿来进行匹配分析,前面有论文表明90%以上的交易都可以分析出来。
产生问题的原因是什么?现在的ZKP方案没有真正解决广大参用户的隐私问题。大多数参与者使用的是手机等轻节点参与交易,不可能作为全节点把所有数据同步到本地的计算机当中。一笔屏蔽交易,解密后才能知道这个交易是不是属于自己,轻节点不可能有所有的数据,它要解密,需要知道一笔交易是不是属于我,必须要将交易密钥交给全节点,这样轻节点隐私得不到很好的保障。并且现在零知识证明方案对轻节点不友好,计算开销大。总的来说现在的隐私安全性等都为全节点设计,没有见到很好的轻节点解决方案。
轻节点对于屏蔽交易支持不足。因为政策的原因,交易所交易就是不让你用屏蔽交易,必须用透明交易。我作为普通用户想要保护自己的隐私,我有一些经验方法,就用尽量使用屏蔽交易,每次交易用不同的新地址,交易金额不同,或者等足够的时间,但是这些不能百分之百保证安全性,你希望有密码的安全性,最佳方案只使用屏蔽交易。但是现实情况不太满足,比如对面要收钱,比如你打钱给交易所,就是不支持屏蔽交易。

四、密码方案风险

零知识证明技术相对较新,16年论文,17年大规模使用,我个人认为这些项目有待时间考验,很多项目参数选择和优化都是比较激进,为了证明方案好。有的困难问题并不标准,依赖太多安全问题,或者缺乏足够多的审计。
这里有一个问题,Zcash的伪造漏洞,CVE-2018-7167,2018年就被发现,但是2019年才被公布。任何人可以伪造证明,凭空创造Zcash这样的货币,这个漏洞其实影响多个Zcash分叉项目。这个漏洞大概花8个月时间才能完成修复,项目方要改变整个证明方案,升级全网。没有人知道漏洞是否被利用,如果被利用也是零知识的,Zcash官方发表声明,很少有人拥有高水平发现漏洞,而且没有发现Zcash总额出现问题。
[BCTV14] 并不存在可证明安全,[BCTV14] 参数生成存在冗余元素,可被利用生成伪造证明,原理并不复杂。后来生成Groth16方案。类似的问题并不是第一次出现,2015年微软研究院研究员发现另外一个漏洞,这些漏洞是不是最后一次,下次影响会不会更大?


我们可以看到Zcash中的有承诺和哈希方案,他的方案非常复杂,仅仅承诺哈希就可能涉及很多方案和很多安全性证明,安全性有待时间考验。

五、其他风险

最后讲讲其他方面的风险,我们可以从数学上证明Groth16是完美零知识方案。实际应用上会有额外的信息漏洞,最明显就是交易里还有密文,密文就不是零知识,完美零知识不等于完美的隐私保护。我的这些数据,我的这些交易都是上链,链的数据可能10年、20年都在上面,可能20年后困难问题被攻破了,曾经的隐私的就都被发现了。
Zcash屏蔽地址不可连接性也存在这样的问题,当前地址不可连接不等于未来不可连接。


侧信道漏洞通常不被重视,这样的攻击利用比较困难,不会直接造成安全问题,但是在隐私相关系统当中是非常重要的。因为侧信道可以直接破坏隐私。我去看了Groth16方案,这也是目前用得最多的零知识证明方案。我要计算证明的时候,就是要计算ABC,这里小写的ai其实就是用户自己手里的秘密,ABC的计算,直接与用户的秘密相关,通过简单的侧信道攻击可以把秘密恢复出来。类似还有Cache测信道攻击。目前这些零知识方案都没有对侧信道攻击做保护。
今天简单分享了ZKP应用的安全风险,零知识证明目前还是新技术,应用中还存在很多问题,当然这些问题会慢慢被解决,越来越成熟。

作者:海伦

文章来源:8btc.com/article/495119

发布于 2019-10-21 11:45