零知识证明(zk-SNARK)(二)

From Computational Problem to zk-SNARK

本部分就是将计算难题转换为多项式,然后使用zk-SNARK。
(注:以下用 P,V 替代 Prover,Verifier)

计算难题->R1CS

R1CS(Rank-1 Constraint System)是一种能够将算数电路统一成约束向量的方式,一组向量构成一组满足特定形式的式子。

计算式拆解

我们知道一般的计算可以拆解为 左操作数 操作符 右操作数 = 输出(如 a × b = c a\times b = c a×b=c)这样的格式,更复杂的计算则是由一系列简单的计算组合而成的。
那么多个操作符应该如何如何表示呢?
多个操作符就需要将其拆分成单个操作符组成式子组,以乘法为界限,例如假设某个计算难题的计算正确计算过程是 a b ( a + c ) = d ab(a+c)=d ab(a+c)=d这个计算式子,有两个乘法,那么就需要拆分成两个式子,如下
{ a × b = e ( a + c ) × e = d \begin{cases} {\color{green}a} \times {\color{blue}b} = {\color{red}e}\\ {\color{green}(a+c)} \times {\color{blue}e} = {\color{red}d} \end{cases} {a×b=e(a+c)×e=d
单看单个操作符的话,绿色就代表 l l l,蓝色就是 r r r,红色则是 o o o
事实上,这就是一个将计算过程化为算数电路的过程,三个颜色分别代表左,右输入和输出。电路中仅有乘法门和加法门,需要注意的是,加法不作为输出,而是直接作为乘法门的输入,这也符合前面提到的操作符以乘法为界限。
强调一下:这里的式子是代表的是某个计算难题的正确计算过程,也可以看作是 P 给 V 的proof 中应该要展示的,证明自己确实用的正确的计算过程。

转化为约束向量

接着把算数电路变换成满足特定形式的式子,如前面的例子

  • 首先对上述式子组中的每一个式子(即,每一个电路门)都生成三个向量(分别称作左向量,右向量和出向量),其维度为不同变量的数目 (例子中为 5 个,每一维分别对应 a , b , c , d , e a,b,c,d,e a,b,c,d,e ), 记式子组式子的数目为 n n n, 记 l i , r i , o i , i ∈ [ n ] l_i,r_i,o_i,i\in [n] li,ri,oii[n]分别为第 i i i 个式子对应的左向量,右向量和出向量。用向量 v = ( v 1 , … , v m ) v=(v_1,\dots,v_m) v=(v1,,vm) 表示 m m m个变量组成的向量,(如这里的 v = ( a , b , c , d , e ) v = (a,b,c,d,e) v=(a,b,c,d,e))

这里就是两个式子,两组共6个向量(每一组都分为左,右,输出三个向量)

  • 向量构造方法是,如果该变量在式子里被使用,就设置为1,否则就设置为0,也就是变量有值即为1,否则为0。

以上面例子为例,可以构造出如下两组向量,每一行对应一个式子
image.png

  • 这时候把向量和 v v v作内积,那么左向量将得到式子的左操作数,右向量和输出向量同理,最终两组向量加上对应操作符将能还原出原式子组。

所以整个式子组便可以表示为
image.png
以上说明了也就是 P 知道原式子的解等价于他知道一组 v v v使得式子组成立。
从计算难题或者说复杂方程转换为特定形式的约束向量就叫做R1CS。

R1CS->QAP

QAP(Quadratic Arithmetic Program):二次算数程序,通俗的说就是给定一系列的多项式以及一个目标多项式,这个集合就是QAP。要达到的目的就是,是否能根据这一系列的多项式,求得它们的一个线性组合,刚好可以整除目标多项式。

转化多项式的思路hint

先从单个操作符的计算式子说起,左操作数 操作符 右操作数 = 输出(如 a × b = c a\times b = c a×b=c)。操作数代表就是实际常量值。
我们知道多项式的计算有不错的算术特性,就是计算某点的值的时候,先带入值计算和先计算再带入值得到的结果是相同的。所以如果我们将操作数表示为多项式的话,同样可以得到经过操作符计算后的结果,那么我们就可以用多项式在某一点的取值去替代掉原来的操作数值。
也就是找到一个多项式 l ( x ) o p e r a t o r r ( x ) = o ( x ) l(x) \ \mathrm{operator} \ r(x) = \ o(x) l(x) operator r(x)= o(x),它满足 l ( a ) o p e r a t o r r ( a ) = o ( a ) l(a) \ \mathrm{operator} \ r(a) = \ o(a) l(a) operator r(a)= o(a)即, l ( x ) l(x) l(x)可以代表在 x = a x=a x=a的时候的左操作数,剩下 r ( x ) , o ( x ) r(x),o(x) r(x),o(x)同理,如果将 a a a代入,就可以得到一般的计算常量式子。一组多项式就会对应这样一个特殊点。
怎么把这里的这种多项式和前面的多项式证明联系起来呢?这里先给一个小小的问题转化思路提示😇,很简单,以只有一个操作符的式子为例,做一个移项,就可以得到 l ( x ) o p e r a t o r r ( x ) − o ( x ) = 0 l(x) \ \mathrm{operator} \ r(x) - \ o(x) = 0 l(x) operator r(x) o(x)=0
这个式子在 x = a x = a x=a为解的情况下该式子就等于 0。也就是计算式计算正确等价于改变后的多项式有特殊解,即必须具有根 x = a x = a x=a,等价于因式分解后必须含有 ( x − a ) (x-a) (xa)这一项。
这样就将一般计算式计算结果的正确性转变为了多项式的结果,某个多项式包含因式,这个因式不就是前面多项式证明里提到的目标多项式 t ( x ) = ( x − a ) t(x) = (x-a) t(x)=(xa)吗?

单个多项式的验证
我们可以定义 p ( x ) = t ( x ) h ( x ) = l ( x ) × r ( x ) − o ( x ) p(x)=t(x)h(x)=l(x) \times r(x)-o(x) p(x)=t(x)h(x)=l(x)×r(x)o(x),移项后即 l ( x ) × r ( x ) = t ( x ) h ( x ) + o ( x ) l(x) \times r(x) = t(x)h(x)+o(x) l(x)×r(x)=t(x)h(x)+o(x)
那么结合前面多项式的证明,证明多项式成立,仅需要证明多项式在某点 s s s的取值成立即可,使用paring 方法, V 的验证变为
image.png
整体的方案变为
image.png
这就是单个操作符乘号的证明思路。

不完整的多个多项式的验证
前面说到多个操作符需要拆分为多个单操作符式子,那么一个式子就可以对应转化为一组 l i ( x ) o p e r a t o r r i ( x ) = o i ( x ) l_i(x) \ \mathrm{operator} \ r_i(x) = \ o_i(x) li(x) operator ri(x)= oi(x),这样就有多组多项式了,那就会对应多个特殊点。
那么如何验证多组多项式呢?
一个最简单的方法就是对单个式子挨个儿进行验证,这显然会使得验证复杂度变得很高,如果能够统一到一个多项式里,那么效率会大大提高。(实际上就是需要统一到一个多项式 )
那么先假设我们已经构造出了这样的多项式(怎么构造下节再说)
像前面一样,前面提到,可以将操作式变为 p ( x ) = l ( x ) × r ( x ) = t ( x ) h ( x ) + o ( x ) p(x)=l(x) \times r(x)=t(x)h(x)+o(x) p(x)=l(x)×r(x)=t(x)h(x)+o(x)来将操作数式子的正确性转变为多项式在某点的结果为0。
以前面的有三个操作符的例子为例,如假设特殊点 x = z i , i ∈ { 1 , 2 , 3 } x = z_i,i\in \{1,2,3\} x=zi,i{1,2,3}时(事实上是可以任意值,这里假设就是1,2,3),整体的多项式结果会是0,也就是说多项式有 x = 1 , 2 , 3 x=1,2,3 x=1,2,3这样三个解,即可以得到 t ( x ) = ( x − 1 ) ( x − 2 ) ( x − 3 ) t(x)=(x-1)(x-2)(x-3) t(x)=(x1)(x2)(x3)。。
那么得到 t ( x ) t(x) t(x)后,证明者 P 就可以计算出 h ( x ) h(x) h(x),从而仿造前面单个式子的协议就可以给出证明。
So,接下来的目标很明确,那就是结合前面的 R1CS 向量表达构造出这样的多项式。

多项式构造

我们知道的是每组 l i ( x ) o p e r a t o r r i ( x ) = o i ( x ) l_i(x) \ \mathrm{operator} \ r_i(x) = \ o_i(x) li(x) operator ri(x)= oi(x)中,一组多项式就对应了一个特殊点,那么多组多项式就会对应多个特殊点,一组多项式满足一个计算式,多组多项式就满足多个计算式,所以一个拥有多个特殊点的多项式,就可以满足多个计算式,也就可以代表整个计算过程。构造多项式就是找到一个多项式(一根曲线)通过了那些特殊点。
l ( x ) l(x) l(x)为例,如将特殊值 x = z i , i ∈ { 1 , 2 , 3 } x = z_i,i\in \{1,2,3\} x=zi,i{1,2,3}作为横坐标(假设就是1,2,3),将 l i ( 1 ) , l i ( 2 ) , l i ( 3 ) l_i(1),l_i(2),l_i(3) li(1),li(2),li(3)的值作为纵坐标,即点 ( 1 , l i ( 1 ) ) , ( 2 , l i ( 2 ) ) , ( 2 , l i ( 2 ) ) (1,l_i(1)),(2,l_i(2)),(2,l_i(2)) (1,li(1)),(2,li(2)),(2,li(2))。( r i ( x ) , o i ( x ) r_i(x),o_i(x) ri(x),oi(x)同理),这就构成了点,由基本的数学定理可以知道, n n n个点可以构成一个唯一的 n − 1 n-1 n1阶的多项式。联立所有的点就可以通过类似拉格朗日插值法合并出一个总的多项式。
举个例子
2 × 1 × 3 × 2 = 12 2 \times 1 \times 3 \times 2 =12 2×1×3×2=12这个计算为例,三个操作符,将其拆分为三个 l e f t × r i g h t = o u t p u t left \ \times \ right = \ output left × right= output的形式
image.png
这里有三个式子,也就是 x = z i , i ∈ { 1 , 2 , 3 } x = z_i,i\in \{1,2,3\} x=zi,i{1,2,3}(假设就是1,2,3),意味着有三组操作数 ( l ( i ) , r ( i ) , o ( i ) ) (l(i),r(i),o(i)) (l(i),r(i),o(i)),进而可以形成三组点
{ l ( x ) : ( 1 , 2 ) , ( 2 , 2 ) , ( 3 , 6 ) r ( x ) : ( 1 , 1 ) , ( 2 , 3 ) , ( 3 , 2 ) o ( x ) : ( 1 , 2 ) , ( 2 , 6 ) , ( 3 , 12 ) \begin{cases} l(x):(1,2),(2,2),(3,6)\\ r(x):(1,1),(2,3),(3,2)\\ o(x):(1,2),(2,6),(3,12) \end{cases} l(x):(1,2),(2,2),(3,6)r(x):(1,1),(2,3),(3,2)o(x):(1,2),(2,6),(3,12)
现在想一想我们要做什么?那就是如何找出能够通过这些点的三个多项式。以 l ( x ) l(x) l(x)为例,我们知道两个点可以解出一个唯一的一次式子,那么 n n n个点,就可以唯一的确定一个 n − 1 n-1 n1阶多项式,所以最后的 l ( x ) l(x) l(x)会是一个 n − 1 n-1 n1阶多项式。
可以计算出
image.png
image.png
image.png
image.png

BUT!注意到在之前的协议中,Setup 阶段限制好了多项式的阶数,Proving 阶段会生成多项式的系数 ,P 能拿到 ( g s i , g α s i ) (g^{s_i},g^{\alpha s_i}) (gsi,gαsi),这就意味着 P 对多项式是有绝对控制权的,也就他可以随意生成多项式,那么他完全有可能生成奇奇怪怪的多项式从而计算毫不相干的东西,同样能够满足 V 的 paring 验证,从而破坏掉协议的一致性
这就像P 向 V 证明,他知道某个难题的解,但是 P 到底没有使用正确的计算方法去计算,V 是无从得知无法验证到的,万一他计算的其他毫不相关的东西呢?
前面的协议中 Verification 阶段只能验证到 P 确实是按照某个多项式进行计算的,但不知道是不是想要的那个,毕竟验证过程里只涉及到了 α − s h i f t \alpha -shift αshift这个用来限制多项式格式的,仅能验证到确实是用了某个多项式,做了相似但不相关的计算。
所以,得保证 P 用的确实是正确的计算方法,也就是需要每个计算式都要满足,顺序不重要,最后结果对就行。

一个解决方案是,把每个生成的多项式加密放到 Setup 阶段去公开,大家都能看到。
然后在 Proving 阶段,让 P 只能用自己知道的解去组合调用这些多项式,生成 proof,这样就可以确保 P 确实是用正确的多项式,达到一致性。(验证方法在后面)


(Wait,不会有人认为,为什么不直接把最终的多项式放到 Setup 阶段吧?那不是谁都可
以证明了吗?那协议还有啥意义呢?)

基础多项式的构造
我们要构造的是满足在特殊点能得到对应结果值(也就是 P 持有的解)的多项式,构造多项式的时候需要用到特殊值以及对应多项式结果组成的点,而解又不能够直接呈现在 Setup 阶段的,而是让 P 在 Proving 阶段再用。所以不能直接生成目标多项式,需要拆开。
于是可以利用多项式的性质,比如我们想得到一个结果为 a a a的式子,就可以先构造一个结果为 1 的多项式,然后再乘以 a a a,这样就能达到目的了。
假设目标结果为 a a a的多项式如下图,
image.png
我们设定的结果为1的基准多项式为,
image.png
把生成的基准多项式放到 Setup 阶段,那么Proving 阶段就仅需带入自己知道的解,就可以完成目标结果的计算了。


(Wait again,为什么不把完整的基准多项式放到 Setup 里呢?因为组合成完整的多项式需要对每个基准多项式乘以对应的系数,介个只有 P 有)


注意到,计算过程的每一步,每个式子都会转换为一组多项式 l i ( x ) o p e r a t o r r i ( x ) = o i ( x ) l_i(x) \ \mathrm{operator} \ r_i(x) = \ o_i(x) li(x) operator ri(x)= oi(x),前面也提到了,如果式子一个一个的验证的话会导致效率很低,所以为了一步到位,我们需要将它们组合成一组整体的多项式,像 L ( x ) o p e r a t o r R ( x ) = O ( x ) L(x) \ \mathrm{operator} \ R(x) = \ O(x) L(x) operator R(x)= O(x)这样,一次就能达成目的。
那么接下来就是构造出结果为1的多项式了。
注意到多项式的算术性质决定了我们可以使用多个同阶的多项式叠加出需要的多项式。
以下面计算式的左操作数为例,左边有两种,三个变量。
image.png
想转化出来的 l ( x ) l(x) l(x)是一个在 x = 1 , x = 2 , x = 3 x=1,x=2,x=3 x=1,x=2,x=3,分别取值 l ( 1 ) = a , l ( 2 ) = a , l ( 3 ) = b l(1)=a,l(2)=a,l(3)=b l(1)=al(2)=al(3)=b的二阶多项式。如图
image.png
三个式子会得到三个 l i ( x ) l_i(x) li(x),比如第一个多项式 l 1 ( x ) l_1(x) l1(x),它是个二阶多项式,让它在 x = 1 x=1 x=1取值为1,在其它 x = 2 , 3 x=2,3 x=23时取值为0; 第二个多项式 l 2 ( x ) l_2(x) l2(x),让它在 x = 2 x=2 x=2取值为1,在其它 x = 1 , 3 x=1,3 x=13时取值为0;第三个多项式 l 3 ( x ) l_3(x) l3(x),让它在 x = 3 x=3 x=3取值为1,在其它 x = 1 , 2 x=1,2 x=12时取值为0。
即三个多项式通过如下点
{ l 1 ( x ) : ( 1 , 1 ) , ( 2 , 0 ) , ( 3 , 0 ) l 2 ( x ) : ( 1 , 0 ) , ( 2 , 1 ) , ( 3 , 0 ) l 3 ( x ) : ( 1 , 0 ) , ( 2 , 0 ) , ( 3 , 1 ) \begin{cases} l_1(x):(1,1),(2,0),(3,0)\\ l_2(x):(1,0),(2,1),(3,0)\\ l_3(x):(1,0),(2,0),(3,1) \end{cases} l1(x):(1,1),(2,0),(3,0)l2(x):(1,0),(2,1),(3,0)l3(x):(1,0),(2,0),(3,1)
这样三个多项式就可以通过类似拉格朗日插值法求出来,每个多项式仅在对应点有意义,在其它点无意义,然后直接加法叠加即可得到结果为1的多项式。还记得R1CS吧?得到 l 1 , l 2 l_1,l_2 l1,l2的向量就是为了辅助完成得到这个多项式。
注意到第一个和第二个都是需要得到结果为 a a a的多项式,所以可以合并起来同时乘以 a a a。于是都乘以解后,可以得到最终的多项式 L ( s ) = a l a ( s ) + b l b ( s ) L(s)=al_a(s)+bl_b(s) L(s)=ala(s)+blb(s)
R1CS中,P 知道原式子的解转换为等价于他知道一组解 v v v,(这是哦),把原式子转化为多项式后,带入这组解就变成能计算出正确结果的多项式,这就和上面对应了。可以以同样的方式构造出 R ( x ) , O ( x ) R(x),O(x) R(x),O(x)
R1CS就可以转换为类似下面这种形式
image.png

更加复杂的多项式构造
目前为止,我们的操作符都是以单个乘法 × \times ×为例的,没有涉及到更加复杂的计算组合,那么下面介绍一下复杂的计算如何转换为多项式。

  • 最简单的加法,比如 ( a + c ) × b = r {\color{green}(a+c)} \times {\color{blue}b} = {\color{red}r} (a+c)×b=r这样的,显然,我们前面构造多项式的方法,是可以允许加法的,只要确保构造单个多项式的时候,满足仅有单个使用的变量具有非零值,而其他变量的都为 0 就可以了。
  • 变量含有常数系数,如 3 a × 2 b = 6 r {\color{green}3a} \times {\color{blue}2b} = {\color{red}6r} 3a×2b=6r,以前构造基准多项式的时候,选择的是取值是 1,这里选择成对应的常数即可,如, l a ( x ) = 3 l_a(x) = 3 la(x)=3,这样再乘以变量就可以还原。
  • 变量加法,比如 a + c = r {\color{green}a+c} = {\color{red}r} a+c=r,我们可以转变为 ( a + c ) × 1 = r {\color{green}(a+c)} \times {\color{blue}1} = {\color{red}r} (a+c)×1=r,后续和前面一样。
  • 变量减法,如 ( a − b ) × 1 = r {\color{green}(a-b)} \times {\color{blue}1} = {\color{red}r} (ab)×1=r,可以向常数系数那样,把取值1,设置为 -1,然后变成一般加法,就像这样 ( a + ( − 1 × b ) ) × 1 = r {\color{green}(a+(-1 \times b))} \times {\color{blue}1} = {\color{red}r} (a+1×b)×1=r
  • 变量除法,如 a ÷ b = r {\color{green}a} \div {\color{blue}b} = {\color{red}r} a÷b=r,可以调换一下顺序,变成乘法如, b × r = a {\color{green}b} \times {\color{blue}r} = {\color{red}a} b×r=a

将更加复杂的问题转换为多项式

  • 范围证明,如证明 0 ≤ a ≤ 15 0 \le a \le 15 0a15,那么可以引入限制式 a = 8 a 3 + 4 a 2 + 2 a 1 + a 0 a = 8a_3+4a_2+2a_1+a_0 a=8a3+4a2+2a1+a0,然后再引入限制式 a i a_i ai等于0或者1即可。
  • 证明一个数 a a a是1还是0,可以引入限制式 a ( a − 1 ) = 0 a(a-1)=0 a(a1)=0
  • 取模函数,可引入 a = k b + r a=kb+r a=kb+r

等等。。
结合多项式验证和多项式构造步骤,找到所有的 { l i ( x ) , r i ( x ) , o i ( x ) } i ∈ { 1 , … , n } \{l_i(x),r_i(x),o_i(x)\}_{i\in\{1,\dots,n\}} {li(x),ri(x),oi(x)}i{1,,n}和目标多项式 t ( x ) t(x) t(x)的步骤就称为 QAP

多项式验证

至此,我们已经构造出了多项式,现在继续多项式验证。前面提到过不完整的验证思路,为什么不完整呢?仅对最后的合并多项式进行检验并不能保证检验的多项式就是目标那个。
因为没有对多项式进行限制的话,那即便是把多项式生成交到 Setup 阶段完成,P 在 Proving 阶段还是可以对 Setup 阶段预定的多项式进行更改的。
所以还需要对此进行限制,强制让 P 使用预定好的多项式。
那么会分有以下情况,

修改多项式
L ( x ) L(x) L(x)为例,理想情况下,我们希望它是由 P 通过 Setup 阶段预先设定好的 l i ( x ) l_i(x) li(x)线性组合出来的。
还记得前面的多项式证明里提到的 α − s h i f t \alpha - shift αshift,这个用来限定多项式的方法,它可以限定多项式的指数,这里同样适用。
回顾一下多项式证明协议的 proving key 和 verification key

image.png

那么 Setup 阶段的Proving key 变成 g l a ( s ) , g α l a ( s ) g^{l_a(s)},g^{\alpha l_a(s)} gla(s),gαla(s),P 能够获取到的就是 proving 和 verification key,即 g l a ( s ) , g α l a ( s ) , g α , g s k g^{l_a(s)},g^{\alpha l_a(s)},g^\alpha,g^{s^k} gla(s),gαla(s),gα,gsk
对一个单一的基准多项式来说,

  • 由于多项式有了加密且不知道 s s s,那么简单修改多项式系数是不可能的;
  • 也不能在里面新增一个预定的多项式,因为 s s s不能直接使用,能用的是 g s k g^{s^k} gsk,如果新增的多项式为 r ( x ) r(x) r(x)的话,意味着只能计算得到 g r ( s ) g^{r(s)} gr(s)得不到 r ( s ) r(s) r(s)。注意,P 也是不知道 α \alpha α的, g α l a ( x ) , g r ( s ) , g α g^{\alpha l_a(x)},g^{r(s)},g^\alpha gαla(x),gr(s),gα是无法产生 g α r ( s ) g^{\alpha r(s)} gαr(s)的,那么势必会破坏掉 α − s h i f t \alpha - shift αshift

所以只能修改整体的多项式的比例,也就是乘以一个常数系数。
对一个组合后的多项式来说,同样可以达到效果,假设 Setup 阶段提供的Proving key 为 ( g l a ( s ) , g α l a ( s ) , g l d ( s ) , g α l d ( s ) ) (g^{l_a(s)},g^{\alpha l_a(s)},g^{l_d(s)},g^{\alpha l_d(s)}) gla(s),gαla(s)gld(s),gαld(s)两组,那么就可以得到 g α L ( x ) = g α l a ( s ) × g α l d ( s ) = g α ( l a ( s ) + l d ( s ) ) g^{\alpha {L(x)}} = g^{\alpha l_a{(s)}} \times g^{\alpha l_d(s)} = g^{\alpha (l_a(s)+l_d(s))} gαL(x)=gαla(s)×gαld(s)=gα(la(s)+ld(s))

但是可能会存在这样一种情况,也就是产生任意的式子,绕过验证,如
image.png
这个后面会提如何解决。
漏或者新增预定的多项式
有两种可能的情况就是,P 可以选择漏掉一个 g l a ( s ) g^{l_a(s)} gla(s),或者重复多次用 g l a ( s ) g^{l_a(s)} gla(s),得到 g α L ( x ) = g α l a ( s ) × g α l a ( s ) × g α l d ( s ) = g α ( 2 l a ( s ) + l d ( s ) ) g^{\alpha {L(x)}} =g^{\alpha l_a{(s)}} \times g^{\alpha l_a{(s)}} \times g^{\alpha l_d(s)} = g^{\alpha (2l_a(s)+l_d(s))} gαL(x)=gαla(s)×gαla(s)×gαld(s)=gα(2la(s)+ld(s))。这会有什么影响呢?事实上,这是无关紧要的。
先看看漏掉一个的情况,假设漏掉一个 g l a ( s ) g^{l_a(s)} gla(s),那么我们知道一个 l i ( x ) l_i(x) li(x)对应的是一组 l i ( x ) o p e r a t o r r i ( x ) = o i ( x ) l_i(x) \ \mathrm{operator} \ r_i(x) = \ o_i(x) li(x) operator ri(x)= oi(x),也就会对应一个计算式,同时也对应了一个解 t i ( x ) = ( x − i ) t_i(x)=(x-i) ti(x)=(xi)。要知道 P 是不知道 t ( x ) t(x) t(x)的,而 V 知道,那么漏掉一个 l a ( x ) l_a(x) la(x),就会导致 t ( x ) t(x) t(x)漏掉一个解 t a ( x ) = ( x − a ) t_a(x)=(x-a) ta(x)=(xa),那验证 p ( x ) = h ( x ) t ( x ) p(x) = h(x)t(x) p(x)=h(x)t(x)的时候,就肯定会失败。
同样如果多次重复使用,可以看到多项式会变成 g α ( 2 l a ( s ) + l d ( s ) ) g^{\alpha (2l_a(s)+l_d(s))} gα(2la(s)+ld(s)),但得注意到 l a ( x ) l_a(x) la(x) 2 l a ( x ) 2l_a(x) 2la(x)对应的解其实是一样的,所以无所谓啦。

多项式复用
比如 o ( x ) × l ( x ) = r ( x ) o(x) \times l(x) = r(x) o(x)×l(x)=r(x) L ( x ) = l a ( x ) + r b ( x ) + o c ( x ) L(x)=l_a(x)+r_b(x)+o_c(x) L(x)=la(x)+rb(x)+oc(x) l ( x ) × l ( x ) = o ( x ) l(x) \times l(x) = o(x) l(x)×l(x)=o(x)d等等情况。
同样可以通过验证。原因就是使用了同一个 α − s h i f t \alpha - shift αshift,所以需要对左右输入和输出使用不同的偏移量,即使用多个 α − s h i f t \alpha - shift αshift,即 α l , α r , α o \alpha_l,\alpha_r,\alpha_o αl,αr,αo。验证的时候分别验证即可。
那么此时的协议就会变成
image.png

变量不一致
注意到 V 在 verification phase 中,仅用 paring 去检验了多项式是否满足 α − s h i f t \alpha - shift αshift。多项式的线性组合系数(变量)是否合适并不能检测到。
那么可能会存在变量不一致的情况,也就是
( g l i ( s ) ) v i , ( g r i ( s ) ) v i , ( g o i ( s ) ) v i (g^{l_i(s)})^{v_i},(g^{r_i(s)})^{v_i},(g^{o_i(s)})^{v_i} (gli(s))vi,(gri(s))vi,(goi(s))vi中的 v i v_i vi,它有可能是不一致的,不一致就会导致某一步中计算的式子不是正确的,而这个按照前面的检验方式也是检测不出来的。
又是类似限制多项式问题,我们可以设立类似 α − s h i f t \alpha - shift αshift的操作,强制让其使用相同的变量,也就是控制比例。如下,用 β − s h i f t \beta - shift βshift来限制整体的系数必须是一样的。
( g l i ( s ) ) v L , i , ( g r i ( s ) ) v R , i , ( g o i ( s ) ) v O , i , ( g β ( l i ( s ) + r i ( s ) + o i ( s ) ) ) v B , i \left(g^{l_i(s)}\right)^{v_{\mathrm{L},i}},\left(g^{r_i(s)}\right)^{v_{\mathrm{R},i}},\left(g^{o_i(s)}\right)^{v_{\mathrm{O},i}},\left(g^{\beta(l_i(s)+r_i(s)+o_i(s))}\right)^{v_{\mathcal{B},i}} (gli(s))vL,i,(gri(s))vR,i,(goi(s))vO,i,(gβ(li(s)+ri(s)+oi(s)))vB,i
也就是 v L , i = v R , i = v O , i = v β , i v_{L,i} = v_{R,i} = v_{O,i} = v_{\beta,i} vL,i=vR,i=vO,i=vβ,i,验证方式如下
e ( g v l , i ⋅ l i ( s ) ⋅ g v R , i ⋅ r i ( s ) ⋅ g v O , i ⋅ o i ( s ) , g β ) = e ( g v B , i ⋅ β ( l i ( s ) + r i ( s ) + o i ( s ) ) , g ) e\left(g^{v_{\mathrm{l},i}\cdot l_i(s)}\cdot g^{v_{\mathrm{R},i}\cdot r_i(s)}\cdot g^{v_{\mathrm{O},i}\cdot o_i(s)},g^\beta\right)=e\left(g^{v_{\mathrm{B},i}\cdot\beta(l_i(s)+r_i(s)+o_i(s))},g\right) e(gvl,ili(s)gvR,iri(s)gvO,ioi(s),gβ)=e(gvB,iβ(li(s)+ri(s)+oi(s)),g)

BUT,也有特殊情况,如 l i ( s ) , r i ( s ) , o i ( s ) l_i(s),r_i(s),o_i(s) li(s),ri(s),oi(s)之间存在相等或者整除之类的关系的话,此时的变量就可以不用一定相等,如假设 l i ( s ) = r i ( s ) = w , y = o ( s ) l_i(s)=r_i(s)=w,y= o(s) li(s)=ri(s)=w,y=o(s),对应的式子变为
β ( v L w + v R w + v O y ) = v β ⋅ β ( w + w + y ) \beta(v_\mathrm{L}w+v_\mathrm{R}w+v_\mathrm{O}y)=v_\mathrm{\beta}\cdot\beta(w+w+y) β(vLw+vRw+vOy)=vββ(w+w+y),此时设 v β = v O , v L = 2 v O − v R v_\beta = v_O,v_L = 2v_O-v_R vβ=vO,vL=2vOvR
显然变量是可以不等的,比如赋值 v L , v R , v O = 1 , 3 , 2 v_L,v_R,v_O = 1,3,2 vL,vR,vO=1,3,2。但是代入式子可以推出
β ( 2 v O w − v R w + v R w + v O y ) = v O ⋅ β ( 2 w + y ) = v β ⋅ β ( 2 w + y ) \beta(2v_\mathrm{O}w-v_\mathrm{R}w+v_\mathrm{R}w+v_\mathrm{O}y)=v_\mathrm{O}\cdot\beta(2w+y)=v_\beta\cdot\beta(2w+y) β(2vOwvRw+vRw+vOy)=vOβ(2w+y)=vββ(2w+y)
则可以通过验证。
所以为了防止这种情况,需要将不同的式子用不同的 β − s h i f t \beta - shift βshift,这样就可以保证即便有倍数或者相等关系,每一个分量也不会成比例。假设有三个,那么 V 需要三个 β l , β r , β o \beta_l,\beta_r,\beta_o βl,βr,βo,用它们对值进行线性组合得到 β l l i ( s ) + β r l r ( s ) + β o l o ( s ) \beta_l l_i(s)+\beta_r l_r(s)+\beta_o l_o(s) βlli(s)+βrlr(s)+βolo(s),此时 P 需要向 V 提供一组同样符合 s h i f t shift shift的线性组合,由于不知道具体的 β i \beta_i βi,故只能采用乘以相同的系数来完成要求。
P 可以计算 g z i ( s ) = ( g β l l i ( s ) + β r r i ( s ) + β o o i ( s ) ) v i g^{z_i(s)}=\left(g^{\beta_ll_i(s)+\beta_rr_i(s)+\beta_oo_i(s)}\right)^{v_i} gzi(s)=(gβlli(s)+βrri(s)+βooi(s))vi然后得到
g Z ( s ) = ∏ i = 1 n g z i ( s ) = g β l L ( s ) + β r R ( s ) + β o O ( s ) g^{Z(s)}=\prod_{i=1}^ng^{z_i(s)}=g^{\beta_lL(s)+\beta_rR(s)+\beta_oO(s)} gZ(s)=i=1ngzi(s)=gβlL(s)+βrR(s)+βoO(s)
验证
e ( g L , g β l ) ⋅ e ( g R , g β r ) ⋅ e ( g O , g β o ) = e ( g Z , g ) e\left(g^L,g^{\beta_l}\right)\cdot e\left(g^R,g^{\beta_r}\right)\cdot e\left(g^O,g^{\beta_o}\right)=e\left(g^Z,g\right) e(gL,gβl)e(gR,gβr)e(gO,gβo)=e(gZ,g),即
e ( g , g ) β l L + β r R + β o O = e ( g , g ) Z e\left(g,g\right)^{\beta_lL+\beta_rR+\beta_oO}=e\left(g,g\right)^Z e(g,g)βlL+βrR+βoO=e(g,g)Z

可塑性问题
由于 P 在进行协议的时候知道proving 和 verification key,以单一的 l ( x ) l(x) l(x)为例,那么 P 就知道了 g α l , g β l , g s k g^{\alpha_l},g^{\beta_l},g^{s^k} gαl,gβl,gsk
这就诞生了多项式的可塑性问题

  • 变量多项式的可塑性问题,就是利用常数项,导致多项式结果变化,同样可以满足 s h i f t shift shift的检验。因为知道 g s k g^{s^k} gsk,用 g s 0 = g g^{s^0} = g gs0=g,就可以计算到 g ( l a ( s ) + l d ( s ) ) × ( g ) 2 = g α ( l a ( s ) + l d ( s ) + 2 ) g^{(l_a(s)+l_d(s))} \times (g)^2 = g^{\alpha (l_a(s)+l_d(s)+2)} g(la(s)+ld(s))×(g)2=gα(la(s)+ld(s)+2)再配合知道 g α g^\alpha gα得到 g α ( l a ( s ) + l d ( s ) ) × ( g α ) 2 = g α ( l a ( s ) + l d ( s ) + 2 ) g^{\alpha (l_a(s)+l_d(s))} \times (g^{\alpha})^2 = g^{\alpha (l_a(s)+l_d(s)+2)} gα(la(s)+ld(s))×(gα)2=gα(la(s)+ld(s)+2)。这样就可以改变结果从而绕过验证。
  • 变量一致性多项式的可塑性问题,和前面一样,可以使用常数配合 g β l g^{\beta_l} gβl来向多项式里添加数来绕过验证。如 g v i β l l i ( s ) × ( g β l ) 2 = g β l ( v i l i ( s ) + 2 ) g^{v_i\beta_l l_i(s)} \times (g^{\beta_l})^2 = g^{\beta_l (v_il_i(s)+2)} gviβlli(s)×(gβl)2=gβl(vili(s)+2)

所以,不能让类似 g α l , g β l g^{\alpha_l},g^{\beta_l} gαl,gβl可见。
一种解决方案是加个掩码,也就是随机产生一个 γ \gamma γ,然后让它们乘以这个随机秘密,即 g β l γ , g β r γ , g β o γ g^{\beta_l \gamma},g^{\beta_r \gamma},g^{\beta_o \gamma} gβlγ,gβrγ,gβoγ,那么与之对应的验证过程变为 e ( g L , g β l γ ) ⋅ e ( g R , g β r γ ) ⋅ e ( g O , g β o γ ) = e ( g Z , g γ ) e\left(g^L,g^{\beta_l\gamma}\right)\cdot e\left(g^R,g^{\beta_r\gamma}\right)\cdot e\left(g^O,g^{\beta_o\gamma}\right)=e\left(g^Z,g^\gamma\right) e(gL,gβlγ)e(gR,gβrγ)e(gO,gβoγ)=e(gZ,gγ)
BUT,如果遇到多项式都是常数的话,也就是如 l 1 ( x ) = 1 , r 1 ( x ) = 0 , o 1 ( x ) = 0 l_1(x)=1,r_1(x)=0,o_1(x)=0 l1(x)=1,r1(x)=0,o1(x)=0,那么还是会暴露,当然前面的一致性检测已经限制了不能随意的添加常数项。

匹诺曹协议

虽然变量一致性检测很有效果,但是在验证中增加了四个 paring 操作,是开销很大的。而匹诺曹协议通过针为左右输入和输出选择了不同的生成元 g l = g ρ l , g r = g ρ r , g o = g ρ o g_l = g^{\rho_l},g_r = g^{\rho_r},g_o = g^{\rho_o} gl=gρl,gr=gρr,go=gρo,满足 ρ l ρ r = ρ o \rho_l \rho_r = \rho_o ρlρr=ρo,然后选择用一个统一的 β \beta β去代替掉其他的 β l , β r , β o \beta_l,\beta_r,\beta_o βl,βr,βo
修改协议如下:
Setup
image.png
Proving
image.png
Verification
image.png

这种方式也能解决,修改多项式中的增加任意式子,绕过验证问题
image.png
因为要更改添加,那 g g g必须是 ρ l , ρ r , ρ o \rho_l,\rho_r,\rho_o ρl,ρr,ρo的倍数,原始的加密方式已经不起作用了。
同时验证的 paring 也缩小为了两次,大大减少开销。

增加零知识性

主要是 P 提供的任何确定性的证明均不能满足零知识的需求,如不能透露变量 v v v的具体赋值,具体的 L ( x ) , R ( x ) , O ( x ) , h ( x ) L(x),R(x),O(x),h(x) L(x),R(x),O(x),h(x)构造方式等等。所以,需要添加掩码,也就是随机 s h i f t shift shift
使得证明看起来和随机数没有什么区别但是能通过验证。
当然,不能单纯使用同一个,不然相同的多项式中即便加入掩码也是会暴露的,为了提高更深的安全性,需要使用多个随机数 δ i \delta_i δi。类似构造如下式子
image.png

其中 Δ \Delta Δ代表平衡左右两边等式的差异值, ? ? ?代表的是运算符号即加减乘除。多项式证明就是证明上面的等式,所以我们需要找到一个合适的能够方便计算出来的差异部分去运用 paring 进行验证。

  • 假设运算符号为乘法,随机选取 δ l , δ r , δ o \delta_l,\delta_r,\delta_o δl,δr,δo,得到

image.png
但是因为介个 δ i \delta_i δi是随机的,不能绝对保证能计算出来这个 Δ \Delta Δ,不是一个整除的结果。
那么赋予随机数一定关系呢?假设满足 δ l δ r = δ o \delta_l\delta_r=\delta_o δlδr=δo,那么有
image.png
这种结构显然的违背了零知识,它会泄露 L ( x ) , R ( x ) , O ( x ) L(x),R(x),O(x) L(x),R(x),O(x)之间的关系,如
e ( g δ l L ( s ) , g δ r R ( s ) ) = e ( g δ o O ( s ) , g ) e(g^{\delta_lL(s)},g^{\delta_rR(s)}) = e(g^{\delta_oO(s)},g) e(gδlL(s),gδrR(s))=e(gδoO(s),g)那么就可以确定 L ( x ) × R ( x ) = O ( x ) L(x)\times R(x)=O(x) L(x)×R(x)=O(x)的关系了。

那么如果改成随机数加法呢?
image.png
注意到,由于介个 δ i \delta_i δi是随机的,所以大概率不能够整除。那么分子同时乘以一个分母 t ( s ) h ( s ) t(s)h(s) t(s)h(s)呢?注意到前面的式子里有 Δ × h ( s ) \Delta \times h(s) Δ×h(s),实际上是加密状态下的,也就是 g Δ × h ( s ) g^{\Delta \times h(s)} gΔ×h(s),但是不支持同态乘法,所以不行。即便可以,要知道 Δ , h ( s ) \Delta , h(s) Δh(s)都是 d d d阶的多项式,乘积就是 2 d 2d 2d阶的, g s i g^{s_i} gsi可是只有 d d d阶的。所以不行。

  • 假设运算符号为加法

image.png
再给分子每一个 δ \delta δ都乘以一个 t ( s ) t(s) t(s),就可以消除掉分母,
image.png
即证明式子变为
image.png

完整的ZKSNARK

image.png
注意 t ( x ) t(x) t(x),基准多项式,生成元,Proving 和 Verification key都是可见的。
image.png

image.png

image.png

参考

浅谈零知识证明:背景与起源
zcash官方科普
Exploring Elliptic Curve Pairings
Quadratic Arithmetic Programs: from Zero to Hero
Why and how zk-SNARK works
ZKSNARK介绍
李威翰,张宗洋,周子博等.简洁非交互零知识证明综述[J].密码学报,2022,9(03):379-447.DOI:10.13868/j.cnki.jcr.000525.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65410.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

jvm的内存区域

JVM 内存分为线程私有区和线程共享区,其中方法区和堆是线程共享区,虚拟机栈、本地方法栈和程序计数器是线程隔离的数据区。 1)程序计数器 程序计数器(Program Counter Register)也被称为 PC 寄存器,是一块…

基于RabbitMQ的模拟消息队列之二---创建项目及核心类

一、创建项目 创建一个SpringBoot项目,环境:JDK8,添加依赖:Spring Web、MyBatis FrameWork(最主要) 二、创建核心类 1.项目分层 2.核心类 在mqserver包中添加一个包,名字为core,表示核心类…

MIPI D-PHY的初始化(MIPI Alliance Xilinx)

DPHY的基本介绍及使用已有很多文章,基本是基于《MIPI Alliance Specification for D-PHY 》的内容,学习时也以此为准,可参考CSDN上的文章。着重讲述MIPI D-PHY的初始化部分 1 D-PHY的功能及使用 下面的文章讲的不错,既有理论&…

iOS swift5 扫描二维码

文章目录 1.生成二维码图片2.扫描二维码(含上下扫描动画)2.1 记得在info.plist中添加相机权限描述 1.生成二维码图片 import UIKit import CoreImagefunc generateQRCode(from string: String) -> UIImage? {let data string.data(using: String.En…

重要变更 | Hugging Face Hub 的 Git 操作不再支持使用密码验证

在 Hugging Face,我们一直致力于提升服务安全性,因此,我们将修改 Hugging Face Hub 的 Git 交互认证方式。 从 2023 年 10 月 1 日 开始,我们将不再接受密码作为命令行 Git 操作的认证方式。我们推荐使用更安全的认证方法&#xf…

A Mathematical Framework for Transformer Circuits—Part (1)

A Mathematical Framework for Transformer Circuits 前言Summary of ResultsREVERSE ENGINEERING RESULTSCONCEPTUAL TAKE-AWAYS Transformer OverviewModel SimplificationsHigh-Level ArchitectureVirtual Weights and the Residual Stream as a Communication ChannelVIRTU…

跳出Lambda表达式forEach()循环解决思路

背景 在一次需求开发时&#xff0c;发现使用Lambda的forEach()跳不出循环。如下示例代码&#xff0c;想在遍历满足条件时跳出循环。 public static void main(String[] args) {List<Integer> list Arrays.asList(1, 4, 5, 7, 9, 11);list.forEach(e -> {if (e % 2 …

ip route get ip地址 应用案例

应用场景 在做虚拟化实验用的虚拟机和实际的ECS云主机一般都会有多个网卡&#xff0c;网络的联通性是经常碰到的问题。比如在一个VM上有3个网卡&#xff0c;分别为ens160(和寄主机进行桥接的网卡10.0.0.128)、ens224&#xff08;连接仅主机网络10.0.0.0/24的网卡10.0.0.128&…

C语言面试题值反转字符串

知识捡漏本 1.C语言优先级 &#xff1a;左高于高于 右 2.定义宏函数product&#xff0c;调用product后&#xff0c;里面的i和i都是加两次1&#xff0c;i就是两个加2后的i相乘&#xff0c;i是开始的i和1后的i相乘。 3.用i (j4,k 8,m 16);这种定义方法&#xff0c;最终i和最后一…

2023最新Python重点知识万字汇总

这是一份来自于 SegmentFault 上的开发者 二十一 总结的 Python 重点。由于总结了太多的东西&#xff0c;所以篇幅有点长&#xff0c;这也是作者"缝缝补补"总结了好久的东西。 **Py2 VS Py3** * print成为了函数&#xff0c;python2是关键字* 不再有unicode对象…

AI图像行为分析算法 opencv

AI图像行为分析算法通过pythonopencv深度学习框架对现场操作行为进行全程实时分析&#xff0c;AI图像行为分析算法通过人工智能视觉能够准确判断出现场人员的作业行为是否符合SOP流程规定&#xff0c;并对违规操作行为进行自动抓拍告警。OpenCV是一个基于Apache2.0许可&#xf…

【Linux】多路IO转接问题-select

select&#xff1a; 首先设置一个lfd绑定服务端地址结构&#xff0c;用于监听新的连接。select函数调用&#xff0c;用于对整个fd数组进行监听&#xff0c;该数组最大限制1024&#xff0c;通过遍历&#xff0c;来确定是哪个fd有变化&#xff1a; 1.如果是lfd&#xff1a;那么可…

Python基础以及代码

Python基础以及代码 1.第一个代码如下&#xff1a; # 项目&#xff1a;第一个项目 # 作者&#xff1a;Adair # 开放时间&#xff1a; 2023/8/15 21:52print("Hello,world!!")如图所示&#xff1a; 2.数字的代码如下&#xff1a; # 项目&#xff1a;演示第一个项…

自然语言处理(六):词的相似性和类比任务

词的相似性和类比任务 在前面的章节中&#xff0c;我们在一个小的数据集上训练了一个word2vec模型&#xff0c;并使用它为一个输入词寻找语义相似的词。实际上&#xff0c;在大型语料库上预先训练的词向量可以应用于下游的自然语言处理任务&#xff0c;为了直观地演示大型语料…

Kubernetes技术--k8s核心技术 Secret

1.概述 Secret 解决了密码、token、密钥等敏感数据的配置问题,而不需要把这些敏感数据暴露到镜像或者 Pod Spec中。Secret可以以 Volume 或者环境变量的方式使用。 作用 加密数据存储在/etc中,使得pod容器以挂载volume方式进行访问。在进行的数据存储中是以base64加密的方式…

C++ struct 笔记(超级详细)

今日碎碎念&#xff1a;我在学C语言时经常用到结构体struct&#xff0c;之后在写C程序时遇到在struct中定义构造函数和成员函数的情况&#xff0c;这在c语言中是从未遇到过的&#xff0c;觉得奇怪&#xff0c;想到之前并没有真正系统学习C里的struct&#xff0c;有必要今天详细…

leetcode - 360周赛

一&#xff0c;2833. 距离原点最远的点 这道题的意思是&#xff0c;遇到 "L" 向左走&#xff0c;遇到 "R" 向右走&#xff0c;遇到 "_" 左右都可以走&#xff0c;那么要想找到距离原点最远的点&#xff0c;就是在找 | "L" "R&qu…

纵行科技与山鹰绿能达成合作,提供物联网资产管理数据服务

近日&#xff0c;纵行科技与山鹰绿能宣布双方达成深度合作关系&#xff0c;纵行科技将为山鹰绿能提供专业的物联网技术服务&#xff0c;使用物联网技术帮助山鹰绿能对循环包装载具等资产进行在线管理和数字化运营。 据悉&#xff0c;山鹰绿能是一家由山鹰国际控股的全资子公司…

前端将UTC时间格式转化为本地时间格式~~uniapp写法

UTC时间格式是什么 首先我们先简单的了解一下&#xff1a;UTC时间&#xff08;协调世界时&#xff0c;Coordinated Universal Time&#xff09;使用24小时制&#xff0c;以小时、分钟、秒和毫秒来表示时间 HH:mm:ss.SSSHH 表示小时&#xff0c;取值范围为00到23。mm 表示分钟…

Compose学习 - 环境配置及compose、kotlin插件、gradle、AndroidStudio版本对应关系

最近学习Compose&#xff0c;一开始学习的Compose版本是1.1.1&#xff0c;学习的过程中发现&#xff0c; LazyHorizontalGrid这个方法只有在1.2.0以后版本才支持。 想着既然要升级&#xff0c;直接用最新的好了。后面按照官网建议&#xff0c;下载了最新的AndroidStudio&#…