零知识证明(一)-基本概念与Schnorr 协议

为何需要零知识

设想一种场景:

1)Alice声称自己研发出了一种可以解所有高考数学题的万能公式,任何题目10秒内都能计算出答案,并愿意以10eth的价格出售;

2)数学成绩一般的Bob表示非常有兴趣。 两人一拍即合。

然而,在交易之际却发生了问题,进入了一个死循环:

1)Alice表示,Bob必须要先付款,不然公式给到了Bob后他偷偷记下,然后拒不支付怎么办?

2)Bob则表示要先验货,如果自己付了钱,拿到的根本不是什么万能公式,Alice割完韭菜卷款跑路,那怎么办?

两人你来我往,尽管双方都有强烈的交易想法,但因为潜在的对手方风险,无人可以让步。最终这笔交易不了了之。

这正是一个典型的例子,“知识的保护”与“证明拥有知识”之间,Alice与Bob未能找到一个调和的方案,最终进入了死锁。 零知识证明(zero-knowledge proof,zk)正是应对这样一个场景而生的技术,即证明某个论点(Alice拥有万能公式)的同时,又不泄露论点中蕴藏的知识(万能公式本身)。

将其衍生到区块链中,数据上链后不可篡改的同时,也牺牲了一定程度的隐私性:用户的某些资产也许并不希望被大众所熟知。 如何即证明用户拥有资产,又不泄露资产的详情与用户的隐私,同样是零知识证明这项技术致力于解决的问题。

在此基础上,回到Alice与Bob的问题,一种能解决双方顾虑的“零知识”方案是:

1)由Bob随机选取题目,对Alice进行挑战;

2)Alice计算答案后供Bob验证正确性与时长。

期间:

1)Alice并未泄露任何有关公式的知识;

2)而Bob则可以任意选取大量的难题、偏题、压轴题;

随着验证数量越来越多,Alice真的拥有万能公式的置信度也就越高。

Schnorr 协议--一个简洁的零知识验证系统

在此基础上来看一个实际的零知识证明协议:Schnorr Protocol。

首先引入些数学铺垫:

有一个形如下图的曲线,我们姑且称之为椭圆曲线:

椭圆曲线
椭圆曲线

此外,我们灵机一动,定义了椭圆曲线上两点P、Q的加法,定义看上去虽然怪但实际运算也很简单:

P+Q = P、Q连线与椭圆曲线的交点(即:G)与X轴的对称点(R)

反映到图中即:P+Q = R

P + Q = R
P + Q = R

如果考虑边界情况,即P、Q是同一个点:P+Q = P+P = 2P,也很简单,将P、Q连线变为P点的切线即可:

P + Q = P + P = 2P = R
P + Q = P + P = 2P = R

以此类推,3P、4P、5P…也非常容易计算。以3P的计算为例,上图中:

3P = P+2P = P + R。又回到了最基础的计算模式。


好了,这就是这部分的主要内容,下面是一个思考问题。根据上述的定义,请举一反三,已知蓝点S = a*P,求解a的值。:

S=aP,a=?
S=aP,a=?

是的,正常情况下应该没有人做出来,尽管已知a后计算aP很简单。但是在仅知道aP的情况下(即已知点S),求解a非常难!这个性质正是密码学安全性的一大基石

(如果真有同学做出来了,我愿意用10eth买你的办法。当然,得先有一个验证,可以是零知识的^_^)

在此铺垫下,终于可以进入本篇章的主题:Schnorr协议。来看这张经典的流程图:

Schnorr协议流程
Schnorr协议流程

Alice手中保管着一个机密的数字a,她用a结合椭圆曲线加法计算出了a*G:

  1. 这里的a就是我们熟悉的私钥private key,需要严格保密;

  2. 这里的PK = aG,就是公钥,公开给大众。因为椭圆曲线的性质,即使大众知道了aG,也很难算出a。

至此,我们来看,Schnorr协议如何简洁地完成一个零知识证明,即Alice向验证者Bob证明自己拥有私钥a的同时,又不泄露a的值:

1)首先,Alice生成了一个随机数r,并计算R = rG,发送至Bob;

(Bob手上的信息:PK 、R)

2)同时,Bob生成一个随机数c,用以挑战Alice*;*

(Bob手上的信息:PK、R、c,他可以基于此计算R+cPK)

3) 最后,Alice需要计算z = r + c*a,并将z回传给Bob。

(Bob手上的信息:PK、R、c、z)

从这一步开始,Bob可以用其手上的信息进行验证:

1)如果Alice确实有a的值,那么Bob利用传回的z,可以计算:

z* G = (r + ca)G = R+ca*G = R+c*PK

应当与步骤2中他的计算结果相等。

2)反之,如果Alice并没有私钥a,她很难猜准z,使得z**G = R+c*PK。

至此Alice手中是否有私钥,得以验证。

同时,回顾Bob的所有信息PK、R、c、z:

1)PK = a*G,因椭圆曲线的性质其很难解出a;

2)R = r*G,r随机生成,和a没什么关系,且无法从R反推r的值;

3)c,Bob随机生成,和a也没什么关系;

4)z = r+c*a,由于r不知,故无法从a = (z-r)/c中解出a的值。

因此纵观整个协议,Bob手上的信息未能透露任何关于a的知识。

可以看到Schnorr协议,使得Alice向验证者Bob证明自己拥有私钥a的同时,又未泄露a的值,简洁地完成了一个零知识证明

零知识证明的三大性质

上文的Schnorr协议让我们看到了一个简洁的零知识证明,但是事情没这么简单。

回顾Schnorr协议的步骤2,Bob生成了用于挑战的随机数c。

如果Alice破解了该随机数生成器的分布,可以预测Bob生成的c,那么她就能伪造R’ = z*G - c*PK, 在不知道a的情况下通过验证,欺骗Bob。

Alice通过破解c值完成欺骗
Alice通过破解c值完成欺骗

而站在Bob的角度,如果他能通过重放攻击,使得Alice连续两次生成同样的随机数r,他就可以借助两次验证的结果,通过(z-z’)/(c-c')反推出a:

Bob重放r来反推a
Bob重放r来反推a

因此看似简单明了的协议,在实现过程中其实存在许多安全问题需要克服。

而理想中,一个零知识证明协议,应当具备如下的三个性质:

1)完备性(completeness):如果Alice拥有a,她就能通过Bob的验证;

2)可靠性(soundness):如果Alice不拥有a,她就不能通过Bob的验证,上文中基于猜测随机数c对Bob进行欺诈就是soundness的反例;

3)零知识(zero-knowledge):验证过程不能泄露a,上文中基于重放r反推出a就是反例。

可见实现一个完美的零知识协议,并能适配通用的应用场景,研发难度相当之大。

回到最初的问题,隐私作为一种强需求有着明确的应用场景,zk会是一种实用的技术,因此值得仔细研究。

本文作为零知识系列的开篇,首先建立一个直观的描述,希望日后不断学习的同时、亦能不断见证零知识技术的成熟。