0%

zcash 零知识证明详解综述

原文:Explaining SNARKs

最近读了 Zcash 的零知识证明科普系列的文章,就在这里做一个总结,记录一下学习过程。

同态隐藏

同态隐藏的定义:E(x)x的函数,该函数满足:

  • 通过E(x)很难推算出x
  • 不同的x会得到不同的E(x)
  • 如果知道E(x)E(y),那么就可以计算出E(x+y)

为什么同态隐藏很有用呢?假设 Alice 想向 Bob 证明她知道 xy 这两个数字,并且 x+y=7,可以这么做:

  1. Alice 把E(x)E(y)发送给 Bob
  2. Bob 通过上面两个值,计算出E(x+y)。(因为E是同态隐藏函数,并且 Bob 也知道这个函数,所以 Bob 可以从E(x)E(y)计算出E(x+y))
  3. Bob 也计算出E(7),如果E(x+y) == E(7),那么 Bob 就承认 Alice 知道xy

多项式和线性组合

定义一个d次多项式P:

我们可以这样在 点上计算 P,让 s 代替 X,并计算总和:

多项式的盲计算

假设 Alice 有一个d次多项式P,Bob有一个随机的点s, 。如果 Bob 想要得出E(P(s)),那么他可以采用如下两种办法:

  1. Alice把P发送给Bob,然后由Bob自己计算出E(P(s))
  2. Bob发送s给Alice,她在计算出E(P(s))之后把结果发给Bob

然后,在盲式计算中,我们想让Bob在无法得知P的情况下得知到E(P(s)) —— 这就否定了第一种办法;但同时,更重要地,我们也不想让Alice得知s,这样也否定了第二种办法。

不过,我们可以用同态隐藏函数进行盲式计算,具体可以这样做:

  1. Bob把隐藏数发送给Alice
  2. Alice通过上面的隐藏数计算出E(P(s)),然后把结果发送给Bob(Alice之所以可以这么做,是因为E支持线性组合,而P(s)就是的线性组合)

你看,我们只发送隐藏数就可以了,Alice不需要得知s,Bob也不需要得知P。看起来我们好像很轻易的就解决了零知识证明所需要的需求,难道真的是这样吗?

当然不是,我们的确利用盲计算将繁琐的计算的过程外包给了他人,也得到了一个结果,但是 Alice 能计算出E(P(x))并不代表她会发送正确的E(P(x))给Bob,她可能会发送一些完全无关的数值。

系数知识测试

对于, 我们定义一个二元组:。如果,那么我就称这个二元组为 二元组。

这个 KC 测试的过程是这样的:

  1. Bob 随机选择。然后计算出
  2. 他把这个二元组(a, b)发给Alice,向Alice发起挑战。注意,(a, b)是一个二元组
  3. Alice必须回应一个不同的二元组(a’, b’)
  4. 只有当(a’, b’)确实是一个 二元组时,Bob才接受Alice

现在,我们来思考一下,Alice应该如何回应这个测试。我们先随便假设一下,如果Alice知道,那么他就可以在G里面任意选择一个a’,然后计算出,并发送(a’, b’)。

然而,关于她唯一知道的只是,而G是具有离散对数难解问题的群,所以我们无法通过

那么,在不知道的情况下,她如何才能正确地回应这个测试呢?

有一个简单的办法:Alice只需要选择一个

因此,我们有:

所以,(a’, b’)确实是一个二元组,符合要求。

需要注意的是,如果Alice通过这种情况来回应测试,那么她就知道了a和a’之间的比值,也就是说,她知道这么一个系数

正如系数知识假设(KCA)所指出的那样,这是不可避免的,也就是说:
KCA: 如果Alice针对Bob的挑战(a, b)给予了一个正确的回应(a’, b’),那么她就知道这样一个

扩展的 KCA

现在,假设Bob不是发送了一个二元组,而是发送了多个(都是同样的),那么,在Alice收到这些二元组之后,Alice需要生成另外的二元组(a’, b’)来完成这个挑战。请记住,Alice必须要能在不知道的情况下完成这个测试。

很自然地,Alice可以从这多个二元组中选择一个出来,然后乘以某个c, ;如果 二元组,那么()也一定是一个二元组。不过,Alice有没有别的方法生成二元组呢?是否可以同时利用几个收到的二元组生成一个新的?

答案是肯定的。例如,Alice可以选择两个值,然后计算出一个二元组。这个可以进行简单的证明,只要a’不是0,那么这个二元组就是二元组:

更一般地,Alice可以使用给定的d个二元组的任意线性组合,也就是:对于任意的,可以定义:

这个扩展的KCA是指,Alice用这种方法生成二元组时,只要她成功了,她就知道a’和之间的线性关系。

更正式的表达是,假设G是一个大小为p的循环群,并且它的生成元是g,那么G的d次系数知识假设(d-KCA)可以表述为:

d-KCA: 设Bob随机选择,并把如下的二元组发送给Alice。如果Alice输出了另一组二元组(a’, b’),那么Alice就会得知

OK,现在我们把上面介绍的各个部分整合一下。

可验证的多项式盲计算协议

假设我们的HH(同态隐藏函数)是:E(x) = x * g,g是上面循环群G的生成元。

由此,我们拿出我们的协议如下:

  1. Bob选择了一个随机的,并把,以及发送给Alice
  2. Alice通过接收到的元素计算出,然后把结果发给Bob
  3. Bob验证一下,如果满足这个等式,则接受Alice

首先,提醒一下,在给定了P的系数之后,的线性组合,的线性组合,那么,根据之前的内容,Alice的确是可以从Bob发送的信息中计算出这些值的。

其次,通过 d-KCA 我们知道,在这整个过程中,Alice知道,使得,所以Alice知道这么一个多项式。也就是说,假如Alice不知道这么个多项式,她瞎蒙一个结果能通过Bob的验证的可能性极小。

运算电路

假设,Alice想要向Bob证明她知道,并使得。第一步,我们先把上面的计算转化一个运算电路。

针对电路的一个合法的赋值,是给被标记线的赋值,使得每个乘法门的输出值确实是相应输入的乘积。

因此,对于我们的电路,一个合乎规范的赋值形式是:

按照这种方式,Alice想要证明的是,她知道一组合法的赋值(。下一步,是使用 QAP 将这个语句翻译成一个多项式。

QAP

我们将每个乘法门与域元素联系起来:联系起来, 联系起来。我们称点{1,2}为我们的目标点。现在,我们需要定义 “左线多项式”集合 , “右线多项式” 集合 以及 “输出多项式” 集合:

这些定义的想法是,非乘法门所涉及的多项式在目标点的取值一般为零。

具体来说,;我们定义,因为多项式2-X,根据,多项式在2点值是0。

注意到的右输入。因此我们同样定义——因为,根据,X-1在目标点2是1,而在另外一个点是0。

我们将其余的多项式都设置成零多项式。(即 )

给定 () 固定值,我们用他们作为系数来定义一个左、右和输出的“和”多项式。也就是说,我们定义:

然后我们定义多项式 P := L * R - O

现在,在完成所有这些定义之后,核心点在于:当且仅当P在所有的目标点上等于0时, ()才是一个对于电路的合法赋值。

我们已知:

让我们使用例子来验证一下。假设我们定义 L,R,O,P ,采用上述给出的。让我们在目标点 1 上计算所有的这些多项式:

在所有的中,只有在1点上是非零的。因此我们有。同样,我们可以得到

因此,。 类似的可以计算出:

换句话说,当且仅当是一组正确的赋值的时候,P在所有的目标点为0

现在,我们使用下面的代数事实:对于一个多项式 P 和一个点 ,当且仅当多项式 X-a 可以整除 P 时,我们有 P(a) = 0 ,比如 P=(X - a) * H ,H是某个多项式。

定义目标多项式 T(X) := (X-1)*(X-2),当且仅当 是一个合法的赋值时,我们有T 能整除 P。

根据上面的讨论,我们对于 QAP 做出如下定义:

一个 d 阶 m 大小的二次算术程序(QAP) Q,由多项式 和 一个d阶目标多项式 T 构成。

如果给() 的赋值满足 Q,定义


P:=L⋅R-O
我们可以确定T可以整除P。

在这个语境中,Alice想要证明她知道一组赋值()满足上述的QAP,并且

总之,我们已经看到,像“我知道这样的语句,是怎么样通过QAP被转换成等价的多项式语句的。

Pinocchio 协议

如果Alice有一个正确的赋值,意思是,像上面那样定义 L,R,O,P ,则存在一个多项式H,使得 P = H T 。特别地,对于任意 ,我们都有P(s) = H(s) T(s)

现在假如Alice没有一个正确的赋值,但是她用一个不满足条件的赋值()构造L, R, O, P,那么我们可以保证T不能整除P。这是说,对于任意一个阶次不大于d的多项式H,P, L, R, O, H都将是不同的多项式。注意,这里的P, L, R, O, H的阶次都最多不会超过2d。

现在我们可以用著名的 Schwartz-Zippel 定理了,它告诉我们,两个不同的阶次不大于2d的多项式,他们最多有2d个共同的点 。因此,如果p比2d大很多,那么随机选择一个s就能满足P(s) = H(s) * T(s)的概率非常低。

于是可以草拟出下面这个可以验证Alice是否有一组正确赋值的协议:

  1. Alice选择如下阶次不大于d的多项式:L, R, O, H。
  2. Bob选择一个随机的点 ,并计算出E(T(s))。
  3. Alice把那些多项式在点s处的隐藏数(E(L(s)), E(R(s)), E(O(s)), E(H(s)))发送给Bob。
  4. Bob检查如下方程是否在s处成立:E(L(s) R(s) - O(s)) = E(T(s) H(s))

再强调一次,如果Alice没有一组正确的赋值,那么她所使用的方程大概率下在s点不能成立,因此,在这种情况,她将不能通过Bob的验证。

如果Alice没有一组正确的赋值,也并不意味着她不能找到任何的阶次不大于d的,并且满足如下条件的L,R,O,H:L R - O = T H。这仅仅是说她不能通过同一组赋值()得到这样的多项式:

之前提到的可验证的多项式盲计算只能保证 Alice 使用了正确阶次的多项式 L,R,O,但不能保证他们是从过同一组赋值产生的。那么我们要如何解决这样的问题呢?

我们把多项式L, R, O组合成一个多项式F:

将R与相乘、O与相乘的原因是,这样L, R, O的系数在F中不会混合:刚好是L的系数,后面d+1个系数刚好是R的系数,最后d+1个系数是O的。

让我们用同样的方式把QAP中的多项式组合起来,给每个定义一个多项式,它的第一部分d+1个系数是的系数,之后的是的系数,再之后是的系数。也就是说,对于每个,我们定义这个多项式:

注意,当我们把两个也分别相加。例如:

如此,我们定义,我们就得到了: 。因此,如果Alice没使用L, R, O, H,而使用了,那么Bob仍能接受。

换句话说,这些多项式在点的计算,没有揭示出任何原有赋值的信息。例如,因为并且是随机的,所以也是一个随机的值,因此,没有揭示出L(s)的任何信息,因为它被随机数给掩盖了。

看起来现在把基本功能都实现了,并且也保证了一定的零知识性,但是我们不难发现,仍然有两个问题困扰着我们:

  1. 在这个协议中,Bob需要一个支持乘法的同态加密函数(HH)。比如,他需要根据计算出。然而,目前为止,我们还没有看到过这种HH的例子,我们只见过可以支持加法和线性组合的HH。

  2. 上述的章节中,我们讨论了Alice和Bob间的交互式协议。不过,我们的最终目标是,能够让Alice发送一个单一的不需要交互的证明信息,并且可以被公开的验证——即,任何人都可以看见这个证明信息,都可以验证她的合法性,而不仅仅是Bob(之前和Alice交流过的那个人)可以验证。