使用zkSnark(一种非交互的自适应知识论证),我们就可以向一个或多个验证者提供一个简短的证明,证明我们对某些私人数据和函数(f)有特定的知识。
使用zkSnark(一种非交互的自适应知识论证),我们就可以向一个或多个验证者提供一个简短的证明,证明我们对某些私人数据和函数(f)有特定的知识。现在让我们一起来了解使用 zkSnark 创建零知识证明的步骤吧。
要运行本教程,你需要安装两个Node.js程序:
npm install snarkjs
npm install circom
在zkSnark中创建零知识证明的第一部分是将函数分解成逻辑步骤。这涉及到创建一个算术电路,它将由基本的加法、减法、乘法和除法运算组成。在本例中,我们将使用:
d = a²+ b
其中a和b是private输入值。然后,我们想证明我们知道输入 a 和 b 的方程的结果,但不会实际给出a、b或d。例如,如果a=3和b=11,答案将是:
d = 3×3 + 11 = 20
我们证明,当 a=3 和 b=11 时(但不泄露这些值),我们知道 d=20。首先,我们将用这个等式(来自名为 mult.circom 的文件)创建一个电路:
pragma circom 2.0.0;template Mult() {
signal input a;
signal input b; signal output d;
var c=0; c = a*a;
d <== c+b;
} component main = Mult();
电路如下:
接下来,我们可以编译电路:
> circom mult.circom --r1cs --wasm --sym --ctemplate instances: 1
non-linear constraints: 0
linear constraints: 0
public inputs: 0
public outputs: 1
private inputs: 2
private outputs: 0
wires: 2
labels: 5
Written successfully: .\mult.r1cs
Written successfully: .\mult.sym
Written successfully: .\mult_cpp\mult.cpp and .\mult_cpp\mult.dat
Written successfully: .\mult_cpp/main.cpp, circom.hpp, calcwit.hpp, calcwit.cpp, fr.hpp, fr.cpp, fr.asm and Makefile
Written successfully: .\mult_js\mult.wasm
Everything went okay, circom safe
接下来,我们创建一个输入文件(input.json)来定义我们的证明:
{"a": 3, "b": 11}
我们还可以使用以下命令将 R1CS 文件导出为 JSON 文件格式:
> snarkjs r1cs export json mult.r1cs mult.json{
"n8": 32,
"prime": "21888242871839275222246405745257275088548364400416034343698204186575808495617",
"nVars": 4,
"nOutputs": 1,
"nPubInputs": 0,
"nPrvInputs": 2,
"nLabels": 4,
"nConstraints": 1,
"useCustomGates": false,
"constraints": [
[
{
"2": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
},
{
"2": "1"
},
{
"1": "21888242871839275222246405745257275088548364400416034343698204186575808495616",
"3": "1"
}
]
],
"map": [
0,
1,
2,
3
],
"customGates": [],
"customGatesUses": []
}
接下来我们必须做的是为电路中给定输入的所有值创建witness。为此,我们可以进入mult_js文件夹,并创建一个witness文件:
\> node generate_witness.js mult.wasm input.json witness.wtns
这就产生了witness.wtns,它将在电路中创造witness的值。我们还可以将我们的witness导出为JSON文件格式:
\> snarkjs wtns export json witness.wtns witness.json
如果我们列出 witness.json,我们会得到:
[ "1", "20", "3", "11" ]
我们现在可以通过Powers of Tau Ceremony:
> snarkjs powersoftau new bn128 12 pot12_0000.ptau -v[DEBUG] snarkJS: Calculating First Challenge Hash
[DEBUG] snarkJS: Calculate Initial Hash: tauG1
[DEBUG] snarkJS: Calculate Initial Hash: tauG2
[DEBUG] snarkJS: Calculate Initial Hash: alphaTauG1
[DEBUG] snarkJS: Calculate Initial Hash: betaTauG1
[DEBUG] snarkJS: Blank Contribution Hash:
786a02f7 42015903 c6c6fd85 2552d272
912f4740 e1584761 8a86e217 f71f5419
d25e1031 afee5853 13896444 934eb04b
903a685b 1448b755 d56f701a fe9be2ce
[INFO] snarkJS: First Contribution Hash:
9e63a5f6 2b96538d aaed2372 481920d1
a40b9195 9ea38ef9 f5f6a303 3b886516
0710d067 c09d0961 5f928ea5 17bcdf49
ad75abd2 c8340b40 0e3b18e9 68b4ffef
和:
> snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="My name" -vEnter a random text. (Entropy): tteesstt112233[DEBUG] snarkJS: Calculating First Challenge Hash
[DEBUG] snarkJS: Calculate Initial Hash: tauG1
[DEBUG] snarkJS: Calculate Initial Hash: tauG2
[DEBUG] snarkJS: Calculate Initial Hash: alphaTauG1
[DEBUG] snarkJS: Calculate Initial Hash: betaTauG1
[DEBUG] snarkJS: processing: tauG1: 0/8191
[DEBUG] snarkJS: processing: tauG2: 0/4096
[DEBUG] snarkJS: processing: alphaTauG1: 0/4096
[DEBUG] snarkJS: processing: betaTauG1: 0/4096
[DEBUG] snarkJS: processing: betaTauG2: 0/1
[INFO] snarkJS: Contribution Response Hash imported:
60736f5b 7484eb59 1e4e57b4 22a6d71f
bdac9cf9 9d8c3583 e4b15191 2094cb2a
b5c51d30 8bc9deee e6df74f9 7e7ccf1d
89ce3c5a 06893553 16c96731 419f3fc7
[INFO] snarkJS: Next Challenge Hash:
75422bee 499a44f2 bdf6d0f5 6b32d5fa
7f8b092b 1c92a093 da1ee4da b64fc2bf
982892a1 7d23a4c3 96006c4f 971c10ee
6d2ae5dd 4a327727 94cedefd 05fdbd12
这将创建一个名为pot12_0000.ptau的文件。
接下来我们将在下一阶段应用我们的电路:
\> snarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -v
然后将创建一个证明和验证密钥(这是在zkey文件中创建的):
\> snarkjs groth16 setup multiplier2.r1cs pot12_final.ptau multiplier2_0000.zkey
然后设置下一个阶段:
> snarkjs powersoftau prepare phase2 pot12_0001.ptau pot12_final.ptau -v[DEBUG] snarkJS: Starting section: tauG1
[DEBUG] snarkJS: tauG1: fft 0 mix start: 0/1
[DEBUG] snarkJS: tauG1: fft 0 mix end: 0/1
[DEBUG] snarkJS: tauG1: fft 1 mix start: 0/1
[DEBUG] snarkJS: tauG1: fft 1 mix end: 0/1
[DEBUG] snarkJS: tauG1: fft 2 mix start: 0/1
[DEBUG] snarkJS: tauG1: fft 2 mix end: 0/1
[DEBUG] snarkJS: tauG1: fft 3 mix start: 0/1
[DEBUG] snarkJS: tauG1: fft 3 mix end: 0/1
.... details missed out
[DEBUG] snarkJS: betaTauG1: fft 11 mix end: 1/2
[DEBUG] snarkJS: betaTauG1: fft 11 join: 11/11
[DEBUG] snarkJS: betaTauG1: fft 11 join 11/11 1/1 0/1
[DEBUG] snarkJS: betaTauG1: fft 12 mix start: 0/2
[DEBUG] snarkJS: betaTauG1: fft 12 mix start: 1/2
[DEBUG] snarkJS: betaTauG1: fft 12 mix end: 0/2
[DEBUG] snarkJS: betaTauG1: fft 12 mix end: 1/2
[DEBUG] snarkJS: betaTauG1: fft 12 join: 12/12
[DEBUG] snarkJS: betaTauG1: fft 12 join 12/12 1/1 0/1
接
下来我们创建密钥:
> snarkjs groth16 setup mult.r1cs pot12_final.ptau mult_0000.zkey[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Reading tauG1
[INFO] snarkJS: Reading tauG2
[INFO] snarkJS: Reading alphatauG1
[INFO] snarkJS: Reading betatauG1
[INFO] snarkJS: Circuit hash:
ac024737 f6a5a4ce 860483b8 515e6915
6205c88a 2e6b7055 f4a03fdb e78c3e4b
c9a7986e 9e8a2cd0 4e28fe88 1cd6c96a
9e569461 1f01666b 6a7ed94a 3504e134
然后为Ceremony作出贡献:
snarkjs zkey contribute mult_0000.zkey mult_0001.zkey --name="Test Name" -vEnter a random text. (Entropy):
Applying key: L Section: 0/2
Applying key: H Section: 0/4
Circuit Hash:
948f8091 7fa93ed2 c1459ef5 0ce43732
d86879cd 267c0625 8ea5c5da d35c6fdc
a61310cf 095f7d39 dc4d4bf9 641c7d4c
df2aae27 fa9d59dd 925d156c 8ecf506b
Contribution Hash:
6bcba108 6554a7c6 aa2bb90d 7c901871
2f0d9bc8 d6f2290b b3850a59 c0c0bdd9
8e61897b eefb0691 5863b31a 2ea8033e
2f880c29 9621d0a7 6ff6e071 007fcd4f
最后,我们可以导出验证密钥:
\> snarkjs zkey export verificationkey mult_0001.zkey verification_key.json
我们现在可以查看验证密钥文件:
{
"protocol": "groth16",
"curve": "bn128",
"nPublic": 1,
"vk_alpha_1": [
"4930972919657545726860728636203202889989795230486834516884623257662010190968",
"17784464477734652112678078638948832338689828495400343595590810154267715615773",
"1"
],
"vk_beta_2": [
[
"18389735958499306728010265966534631076957479993331219391194646786717212290454",
"9377762495436441301891640165839693718450498177510036079594436038367782263806"
],
[
"12918025179235334873924565184099963869927560708469813538777622359611980563600",
"9540299846849550800883433886871516082732747826796133848225752385718676233704"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"10857046999023057135944570762232829481370756359578518086990519993285655852781",
"11559732032986387107991004021392285783925812861821192530917403151452391805634"
],
[
"8495653923123431417604973247489272438418190587263600148770280649306958101930",
"4082367875863433681332203403145435568316851327593401208105741076214120093531"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"6678561741832709084950120792594057740372012012476808764391217711675983692110",
"19148562476715307366333124452364601954136306739968359421280546942781306687117"
],
[
"5563686774264337713632059638379062839883993286221464997715904103056019482412",
"21833682533925220432016594073010435262143992710094235623186050651622850207784"
],
[
"1",
"0"
]
],
"vk_alphabeta_12": [
[
[
"21035614430046395676452458856349037799926906859868468846877507191464853481937",
"7367376076358797456371954886520136044173614048593332592178094606599134546984"
],
[
"5808825009653597050362562643979192678810121406759169545733784434854763413918",
"15128225491901928330780610339864969395330419807108978760255288410444914516625"
],
[
"14978815026753531164200162544695939844698822789400754850228256443689058138231",
"16113300741635819930196783951232141998238231281531753181323378044203883884342"
]
],
[
[
"8442579491476795281405460092751645692381846639953353246612942751519012569788",
"11827292701507789496064142034155273588916516375204067786052314521160910352971"
],
[
"20072517047914614006053365712147494445532735080074807478164761993842384472110",
"13665874946665444505746003584809490872324268348019328507331521810995839980467"
],
[
"10225689113248454267459923513638914637857045930066471172993596968519514548462",
"6383370432527878416577498240685833420691833124835369534381884954863421906203"
]
]
],
"IC": [
[
"18715829740044647887122344913298058336630317728738304325862477358219862297827",
"16221092531741964322070455355625510828324417870530275245397592617997280882899",
"1"
],
[
"673958305085585829783514648122080086902081959530482708587291142529753209278",
"6811756694984425962860666144580149688381174003774696142976434024786320245650",
"1"
]
]
}
现在我们有了可以根据witness文件创建证明的文件:
\> snarkjs groth16 prove mult_0001.zkey witness.wtns proof.json public.json
输出将是proof.json,它包含了我们的知识证明:
{
"pi_a": [
"18179065977147657779359641627266856730189560012430348972168729148195594119398",
"4325130652974965851962487796548080753812713465953132240508427612753615137668",
"1"
],
"pi_b": [
[
"18395390851775000847122561780630950260849796100997778613417368640548299239475",
"17639909396142653244025863699056463248483166788147768144883360518935838049735"
],
[
"9408131275963864266616099995774753746213060751552818483760857814043622474916",
"8981404227605788652195858905745591103367179864186050631891035451705025332378"
],
[
"1",
"0"
]
],
"pi_c": [
"1737020500140345915930097080595151095303222939533212987558942021306795966145",
"145473143193388753772867796175071880043993095936447841945077555539388439000",
"1"
],
"protocol": "groth16",
"curve": "bn128"
}
和public.json:
[
"20"
]
我们也可以检查验证密钥,看看它对证明是否有效:
> snarkjs zkey verify mult.r1cs pot12_final.ptau mult_0000.zkey[INFO] snarkJS: Reading r1cs
[INFO] snarkJS: Reading tauG1
[INFO] snarkJS: Reading tauG2
[INFO] snarkJS: Reading alphatauG1
[INFO] snarkJS: Reading betatauG1
[INFO] snarkJS: Circuit hash:
c2d18bee ad37bdb0 ff2f6443 7ba50f8a
a6ee3552 8356a79c e14ed342 58adecd3
6c5068ac f7113bbb c68d2752 9abc0a6f
9ec007a6 73401931 67d58666 5fa6b5d5
[INFO] snarkJS: Circuit Hash:
c2d18bee ad37bdb0 ff2f6443 7ba50f8a
a6ee3552 8356a79c e14ed342 58adecd3
6c5068ac f7113bbb c68d2752 9abc0a6f
9ec007a6 73401931 67d58666 5fa6b5d5
[INFO] snarkJS: -------------------------
[INFO] snarkJS: ZKey Ok!
最后,我们可以取proof、public value、verification,证明这个proof是有效的:
> snarkjs groth16 verify verification_key.json public.json proof.jsonsnarkJS: OK!
现在让我们在Golang中创建一个程序,它将读取验证密钥、公共值和证明:
package main
import (
"fmt"
"io/ioutil"
"github.com/iden3/go-circom-prover-verifier/parsers"
"github.com/iden3/go-circom-prover-verifier/verifier"
)
func main() {
fmt.Println("zkSNARK Groth16 verify")
proofJson, _ := ioutil.ReadFile( "proof.json")
vkJson, _ := ioutil.ReadFile("verification_key.json")
publicJson,_ := ioutil.ReadFile("public.json")
public, _ := parsers.ParsePublicSignals(publicJson)
proof, _ := parsers.ParseProof(proofJson)
vk, _ := parsers.ParseVk(vkJson)
v := verifier.Verify(vk, proof, public)
fmt.Printf("%v",v)
}
示例运行:
go-circom-prover-verifier
zkSNARK Groth16 prover
true
已经完成了。
zkSnark是目前计算机科学和网络安全领域最热门的话题之一,它可以被用来证明知识——比如你有一个私钥或密码——但却不用真正泄露它。如果可以加入智能合约的力量,我们就能够创造一个全新的信任世界。
下面是完整的教程:
https://asecuritysite.com/zero/zksnark03
ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!