白話零知識證實(二)

hi 歡迎來到小祕課堂第三期,今天咱們來說講白話零知識證實(二)的那些事兒,歡迎主講人馬宇峯git

 講師:馬宇峯github

編輯: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.spa

首先咱們將這個方程用一種特殊的程序語言來表達3d

咱們這裏所使用的特殊的程序語言支持基本算術運算 (+,-,*,/),常量階指數運算(如:能夠計算 可是不能計算 ) 和變量賦值,理論上能夠在這個語言中作任意計算(只要計算步驟的次數是受限制的,此外,不容許循環)。注意,這個語言不支持模運算 (%) 和比較運算 (<, >, <=, >=),可是經過提供輔助輸入能夠擴展到支持這兩種運算,此處咱們不作展開。blog

下一步是「拍平」(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 

相關文章
相關標籤/搜索