hi 欢迎来到小秘课堂第三期,今天我们来讲讲白话零知识证明(二)的那些事儿,欢迎主讲人马宇峰
讲师:马宇峰
编辑:Leo
前言
本文是建立在 Vitalik 的博客《Quadratic Arithmetic Programs: from Zero to Hero》基础之上,加上一点点自己的理解写成的。相信许多小伙伴和我一样,在阅读各种关于 zk-SNARK 的论文和博客过程中,都曾被 QAP 搞得一头雾水,Vitalik 这篇博客的厉害之处就在于他把计算问题转换为 R1CS,再把 R1CS 转换成 QAP 问题的过程描述的很清楚。
QAP问题
首先,zk-SNARK 不能直接用于解决任何计算问题,我们必须先把问题转换成正确的“形式”来处理,这种形式叫做 "quadratic arithmetic problem"(QAP),在进行 QAP 转换的同时,如果你有代码的输入就可以创建一个对应的解(有时称之为 QAP 的 witness)。之后,还需要一个相当复杂的步骤来为 witness 创建实际的“零知识证明”,此外还有一个独立的过程来验证某人发送给你的证明。
举例说明
我们来选择一个简单的例子来做说明:证明你知道一个立方方程的解:
(提示:解是 3,解用来构造 witness)。这个例子既可以让你理解 zk-SNARK 背后的技术原理,又不会产生出很大的 QAP.
首先我们将这个方程用一种特殊的程序语言来表达
我们这里所使用的特殊的程序语言支持基本算术运算 (+,-,*,/),常量阶指数运算(如:可以计算 但是不能计算 ) 和变量赋值,理论上可以在这个语言中做任意计算(只要计算步骤的次数是受限制的,此外,不允许循环)。注意,这个语言不支持模运算 (%) 和比较运算 (<, >, <=, >=),但是通过提供辅助输入可以扩展到支持这两种运算,此处我们不做展开。
下一步是“拍平”(Flattening),我们要将刚才的代码转换成一系列只包含以下两种形式的声明
1:x = y ( y 可以是变量或者数字)
2:x = y op z ( op 是二元运算符,可以是 (+, - , *, /) 运算,y,z 可以是变量,数字或者子表达式 )
“拍平”后的结果是:
你可以认为上述的每一行声明都是一个电路中的逻辑门,与原始代码相比,这里我们引入了两个中间变量 sym_1 和 sym_2,还有一个表示输出的冗余变量 ~out,不难看出 “拍平” 后的声明序列和原始代码是等价的。
接下来我们要把上述结果转化成R1CS(rank-1 constraint system,一阶约束系统)
R1CS 是一个由三向量组 (a,b,c) 组成的序列,R1CS 有个解向量 s,s 必须满足,符号表示向量的内积运算。这里的解向量 s 就是 witness。举个例子:
a = (5,0,0,0,0,1),
b = (1,0,0,0,0,0),
c = (0,0,1,0,0,0),
s = (1,3,35,9,27,30),
是一个满足的 R1CS,通过下图可以更直观的看出运算过程:
上述例子只有一个约束,接下来我们要将每个逻辑门 (即“拍平”后的每一个声明语句) 转化成一个约束(即一个三向量组),转化的方法取决于声明是什么运算 (+,-,*,/) 和声明的参数是变量还是数字。
在我们这个例子中,除了“拍平”后的五个变量 ('x', '~out', 'sym_1', 'y', 'sym_2') 外,还需要在第一个分量位置处引入一个冗余变量 ~one 来表示数字 1,就我们这个系统而言,一个向量所对应的 6 个分量是 (可以是其他顺序,只要对应起来即可):
'~one',' x', '~out', 'sym_1', 'y', 'sym_2' 解向量是以这个顺序对这些变量所赋的值。
通常,我们得到的向量都是稀疏的,现在我们给出第一个门 的三向量组 (a,b,c):
'~one', ' x', '~out', 'sym_1', 'y', 'sym_2'
a = [0, 1, 0, 0, 0, 0]
b = [0, 1, 0, 0, 0, 0]
c = [0, 0, 0, 1, 0, 0]
可以看出如果解向量s的第二个标量是 3,第四个标量是 9,无论其他标量是多少,都有
,同样,如果 s 的第二个标量是 7,第四个标量是 49,也会通过检查,第一次检查仅仅是为了验证第一个门的输入和输出的一致性。
类似的第二个门 的三向量组 (a,b,c) 为:
'~one', ' x', '~out', 'sym_1', 'y', 'sym_2'
a = [0, 0, 0, 1, 0, 0]
b = [0, 1, 0, 0, 0, 0]
c = [0, 0, 0, 0, 1, 0]
第三个门 的三向量组 (a,b,c) 为:
'~one', ' x', '~out', 'sym_1', 'y', 'sym_2'
a = [0, 1, 0, 0, 1, 0]
b = [1, 0, 0, 0, 0, 0]
c = [0, 0, 0, 0, 0, 1]
加法的转化方式略有不同,我们应该理解为 (x + y)*1 - sym_2 类似的,最后一个门 的三向量组 (a,b,c) 为:
'~one', ' x', '~out', 'sym_1', 'y', 'sym_2'
a = [5, 0, 0, 0, 0, 1]
b = [1, 0, 0, 0, 0, 0]
c = [0, 0, 1, 0, 0, 0]
好了,我们现在已经做了最后一次验证:
~out = sym_2 + 5.
witness(即解向量)是 [1,3,35,9,27,30]。(因为我们知道 x=3,将它带入“拍平”后的声明语句就可得到其他变量的解)。
现在我们得到了四个约束的 R1CS,完整的 R1CS 如下:
A
[0, 1, 0, 0, 0, 0]
[0, 0, 0, 1, 0, 0]
[0, 1, 0, 0, 1, 0]
[5, 0, 0, 0, 0, 1]
B
[0, 1, 0, 0, 0, 0]
[0, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
[1, 0, 0, 0, 0, 0]
C
[0, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 1]
[0, 0, 1, 0, 0, 0]
接下来我们要做的是将R1CS转化成QAP形式
这两者的区别是 QAP 使用多项式来代替点积运算,他们所实现的逻辑完全相同。在介绍这种转化之前,我们需要学习拉格朗日差值公式,这个公式的作用是构造一个穿过指定点的多项式,Vitalik 的文章中用了很大的篇幅介绍这个公式的使用,在这里我直接给出拉格朗日插值公式:
通过 n 个点 的 n-1 阶多项式为
例如通过点 (1,3), (2,2), (3,4) 的多项式为:
好了,学会使用这个公式后可以继续我们的步骤了。现在我们要将四个长度为六的三向量组转化为六组多项式,每组多项式包括三个三阶多项式,我们在每个x点处来评估不同的约束,在这里,我们共有四个约束,因此我们分别用多项式在 x = 1,2,3,4 处来评估这四个向量组。现在我们使用拉格朗日差值公式来将 R1CS 转化为 QAP 形式。
我们先求出四个约束所对应的每个 a 向量的第一个值的多项式,也就是说使用拉格朗日插值定理求过点 (1,0), (2,0), (3,0), (4,0) 的多项式,类似的我们可以求出其余的四个约束所对应的每个向量的第i个值的多项式。结果如下:
A 多项式组
[-5.0, 9.166, -5.0, 0.833]
[8.0, -11.333, 5.0, -0.666]
[0.0, 0.0, 0.0, 0.0]
[-6.0, 9.5, -4.0, 0.5]
[4.0, -7.0, 3.5, -0.5]
[-1.0, 1.833, -1.0, 0.166]
B 多项式组
[3.0, -5.166, 2.5, -0.333]
[-2.0, 5.166, -2.5, 0.333]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
C 多项式组
[0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0]
[-1.0, 1.833, -1.0, 0.166]
[4.0, -4.333, 1.5, -0.166]
[-6.0, 9.5, -4.0, 0.5]
[4.0, -7.0, 3.5, -0.5]
这些系数是升序排序的,例如上述第一个多项式是 0.833x3 - 5x2 +9.166x -5. 如果我们将 x=1 带入上述十八个多项式,可以得到第一个约束的三个向量 (0, 1, 0, 0, 0, 0), (0, 1, 0, 0, 0, 0), (0, 0, 0, 1, 0, 0), 类似的我们将 x = 2, 3, 4 带入上述多项式可以恢复出 R1CS 的剩余部分。
通过将 R1CS 转换成 QAP 我们可以通过多项式的内积运算来同时检查所有的约束而不是像 R1CS 那样单独的检查每一个约束。如下图所示:
我们需要检查结果多项式 A(x) * B(x) - C(x) 在 x=1,2,3,4 处是否都为 0,若在这四个点处有一处不为 0,那么验证失败,否则,验证成功。
根据代数学原理,正确性检查等价于结果多项式 A(x) * B(x) - C(x) 是否能够整除多项式 Z(x) = (x-1)(x-2)(x-3)(x-4). 不难看出多项式 Z(x) 是根据所有逻辑门约束条件所对应的点算出来的。通过这种等价形式的转化会大大减少我们的开销。
写到这里 zk-SNARK 的基本原理就算讲清楚了,后续都是一些优化过程,比如说我们的多项式系数是小数,这样会有舍入误差,在实际中我们会在有限域上做算术运算,这样结果都是整数,不存在舍入误差了。还有我们会将多项式验证转化为椭圆曲线上的双线性对运算来验证,这样可以进一步降低时间开销。
剩余部分
在完成我们的剩余部分前,我们需要先了解一些椭圆曲线对运算的知识,在这里我们仅介绍椭圆曲线对运算的一些性质,懂得这些性质就可以理解后续内容,有关椭圆曲线对运算的详细介绍,可以参考 Vitalik 的 blog。
关于椭圆曲线你需要知道以下知识:
1)椭圆曲线有一个 "生成点" G,G 做 n 次加法运算后可得到椭圆曲线上的所有点,n 称为椭圆曲线的阶。
2)当 d 足够大时,知道椭圆曲线上的两个点 P, Q 其中 Q = d*P,求 d 困难,这就是椭圆曲线上的离散对数问题。
设 P,Q,R,S 是椭圆曲线上的点,a,b 是整数,关于椭圆曲线对运算你需要知道以下性质:
1. e(aP, bQ) = e(P, Q)ab
2. e(P, Q+R) = e(P, Q)*e(P, R)
3. e(P+S, Q) = e(P, Q)*e(S, Q)
好,现在我们看看刚才学的知识的作用:如果你使用椭圆曲线上点 G 对一个数字 p 进行单项加密:
encrypt(p) = p*G = P,
椭圆曲线可以检查数字的线性组合,例如(大写字母表示椭圆曲线上的点,小写字母表示数字):
P = p*G, Q = q*G, R = r*G
检查
5*p + 7*q = 11 *r
相当于检查
5*P + 7*Q = 11 *R
这说明椭圆曲线具有同态性。
椭圆曲线上的对运算可以检查二次约束,例如:
检查
e(P, Q)*e(G, G*5)=1
相当于检查
p*q + 5 = 0.
目前为止我们已经了解了 QAP,可以将任何计算问题转化为多项式等式形式,这样可以更容易验证数学欺骗。此外我们也了解了椭圆曲线对运算,可以做等值验证。
下面我们要利用椭圆曲线对运算和其他的数学技巧来让证明者在不泄露解信息的情况下证明他知道一个 QAP 的解。
首先我们要引入KEA (指数知识假设, knowledge-of-exponent assumption)
在椭圆曲线上,KEA 指的是给定一对点 P, Q,其中 P*k = Q,然后在给定一个点 C,你不可能得到一个点 R = C *k,除非你知道 C 是怎样有点 P “派生” 出来的(例如,你知道 C = n*P 中的 n,那么 C*k=n*P*k=n*k*P=n*Q)。
以上是指数知识假设,zk-SNARK 的安全性依赖于这个假设,尽管 KEA 还没有被证明等价于其他困难问题(如离散对数问题),但是大多数密码学家认为它足够坚固。
下面我们看一下对椭圆曲线运算是怎样运用对运算的
假设现在有一对点 (P, Q) 其中 P*k = Q,没人知道 k 的值是什么,我得到这对点之后我给出一对新的点 (R, S) 并声称 R*k = S. 指数知识假设可以保证我能得到这对点的唯一途径是我用点 P 和 Q 同时乘以一个只有我自己知道的值 r. 通过椭圆曲线对运算的性质,我们可以在不需要知道 k 的情况下验证 R*k = S 是否成立:
e(R, Q) ?= e(P, S).
现在我们进一步给定十对点 (P1, Q1), (P2, Q2),...,(P10, Q10),每对点都有 Pi*k=Qi. 类似的,我给出一对新的点 (R, S) 并声称 R*k = S,这时可以推出我知道 R 是 P1,P2,...P10 的线性组合:
P1*i1+P2*i2+...+P10*i10,S 是点 Q1,Q2,...,Q10 使用同样系数的线性组合。我们可以使用同样的方法来验证 R*k = S.回顾一下我们刚刚讲的 QAP 的解是这种形式的:
A(x) * B(x) - C(x) = H(x) * Z(x).
其中:
多项式 A(X) 是多项式组 {A1(x), A2(x),..., A6(x)} 的线性组合;
多项式 B(X)是与 A(x) 相同系数的多项式组 {B1(x), B2(x),..., B6(x)} 的线性组合;
多项式 C(X) 是与 A(x) 相同系数的多项式组 {C1(x), C2(x),..., C6(x)} 的线性组合;
注意,在实际使用中多项式 A(X), B(X), C(X) 是很大的,可能会有上万个子项,因此证明者提供一个多项式的线性组合会很复杂。根据 Schwartz-Zippel 定理,两个 2d 阶(最高阶是 2d )多项式最多在 2d 个点处值相等,因此我们选一个随机值 t (由于我们所使用的有限域的阶远大于多项式的阶,因此找到另一个多项式使得这个多项式在t处取值和此多项式相等的概率小到可以忽略),来验证 A(t) * B(t) - C(t) ?= H(t) * Z(t) .
我们通过椭圆曲线上的对运算进一步降低计算量,设 G 是椭圆曲线的生成点(基点),证明者需要给出以下证明:
πA = G * A(t), πA' = G*A(t)*ka
πB = G * B(t), πB' = G*B(t)*kb
πC = G * C(t), πC' = G*C(t)*kc
πH = G * H(t)
验证者检查:
e(πA, πB)/e(πC, G)?=e(πH, G*Z(t))
到这里 zk-SNARK 的基本原理就讲完了,本文通过一个例子详细介绍了怎样将计算问题转化为 QAP形式,后面的部分写的有些简单,但是足够让大家理解 zk-SNARK 的基本原理。
关于讲师
马宇峰(Cris Ma)
秘猿科技研究院密码学研究员
秘猿科技 repo:https://github.com/cryptape
连接开发者与运营方的合作平台 CITAHub:https://www.citahub.com/
有任何技术问题可以在论坛讨论:https://talk.nervos.org
本文中涉及到的参考文献如下:
1.《Quadratic Arithmetic Programs: from Zero to Hero》
https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649
2.《Exploring Elliptic Curve Pairings 》
https://medium.com/@VitalikButerin/exploring-elliptic-curve-pairings-c73c1864e627
3.《Zk-SNARKs: Under the Hood 》
https://medium.com/@VitalikButerin/zk-snarks-under-the-hood-b33151a013f6
相关推荐
这些文件可能会涵盖以下知识点: 1. **零信任框架**:解释零信任模型的构成部分,包括身份验证、授权、加密、微隔离、持续监控等核心元素。 2. **身份验证技术**:介绍多因素认证(MFA)、单点登录(SSO)、身份和...
4. **培训教材**:这部分资料可能是为培训员工理解和执行零信任策略而设计的,涵盖了理论知识、操作流程和实战技能。通过这些教材,员工可以更好地理解零信任的重要性,学习如何在日常工作中实施零信任原则。 5. **...
白话 C++ 第二学堂 适合入门级C++的学习,比较全的C++细节知识
系统介绍零信任产生背景、零信任原则、标准化进展、零信任与传统边界安全理念的比较、零信任参考架构、零信任实现方案、零信任应用场景、零信任落地指引、行业客户案例等内容
子平真诠白话解释 子平真诠白话解释是对《子平真诠》书中语言的白话形式记录。《子平真诠》书中语言虽接近现在,但也有不少生涩的地方;因此,需要将其语义以现在白话形式记录下来,方便自己日后翻看。 子平真诠...
在《白话C++》中,作者首先会介绍C++的基础知识,包括基本数据类型、变量、运算符、流程控制语句(如if-else、switch-case、for、while等),以及函数的使用。这些基础知识是学习任何编程语言的基石,对于理解后续的...
白话中台战略-中台是个什么鬼.pdf白话中台战略-中台是个什么鬼.pdf白话中台战略-中台是个什么鬼.pdf白话中台战略-中台是个什么鬼.pdf白话中台战略-中台是个什么鬼.pdf白话中台战略-中台是个什么鬼.pdf白话中台战略-...
"白话C++编程"这个资源显然旨在以通俗易懂的方式介绍C++编程的基础知识,这对于初学者或者需要巩固基础的开发者来说是非常有价值的。以下是基于这个主题的详细知识点解释: 1. **C++简介**:C++是C语言的一个扩展,...
白话机器学习的数学-立石贤吾-源代码.zip
《罗织经》白话全译.doc
### 白话C++ 关键知识点解析 #### 1. 计算机基本概念:硬件与软件 **硬件**:指的是计算机系统中的物理组件,包括中央处理器(CPU)、内存(RAM)、硬盘驱动器(HDD)、输入输出设备(如键盘、鼠标、显示器)等。...
标题中的"白话经典控制理论"告诉我们,本文将采用通俗易懂的语言来介绍控制理论,避免了复杂的数学表达和难以理解的术语,使没有专业背景的读者也能理解控制理论的基本概念。 描述部分进一步强调,本文的目的是普及...
### 白话Windows编程知识点详解 #### 一、消息的概念 **消息**是Windows操作系统中一个非常核心且基础的概念,它是程序之间以及程序内部不同组件之间进行通信的主要方式。简单来说,消息是一种软件机制,用来通知...
《白话 Windows 编程》EXE格式电子书,收藏版!!!
此外,错误处理和调试技巧也是必不可少的知识点,它们帮助开发者识别和修复程序中的问题。 总的来说,《白话Windows编程》这本书旨在让读者通过C++语言掌握Windows平台下的程序设计,从基础到进阶,一步步引导读者...
本书对统计学原理和术语进行了简洁、清晰而准确的解释,并通过大量实例讲述统计技术的操作方法。书中涵盖了社会科学研究所使用的大部分统计原理和方法,诸如集中趋势、变异程度、正态分布、z分数、标准误等基本概念...
白话文运动的危机,CAJViewer 文件,使用CAJViewer软件查看