前言:本文我们使用两个公开库circom、snarkjs尝试构建一个简单的零知识证明。其中,circom库用于构建和编译代数电路,snarkjs库是zk-snarks协议的独立实现。本文使用的方法主要参考的是snarkjs库0.4.6官方教程(英文)和博文circom与snarkjs经典教程(中文)。感谢这两篇文献的作者。

另,github上面也给出了一个较为完整的英文版的tutorial,感兴趣的盆友可以点击链接​​​​​​​学习。

目录

准备:安装Node.js

1. 安装circom&snarkjs

2. 可信设置

3.  构建电路

4. 生成groth16算法密钥

5. 计算见证(witness)

6. 证明与验证


准备:安装Node.js

具体方法参考我的另一篇博文。

1. 安装circom&snarkjs

在终端输入如下安装命令:

npm install -g circom
npm install -g snarkjs

在执行第二条命令时出现git报错:

上网搜索发现可能原因是(1) ipv6,(2) 之前开了网络代理,git默认走代理通道,导致现在关掉代理之后用不了了。

方法1:在终端输入如下命令禁用ipv6:

networksetup -setv6off Wi-Fi

方法2: 首先查看git配置,在终端输入“git config --global --list ”,若发现返回内容中包含http.https或者https.https字样,说明设置了网络代理。输入如下命令撤掉代理即可:

git config --global --unset http.proxy
git config --global --unset https.proxy

我遇到的是问题(1),使用方法1解决了。

2. 可信设置

2.1 创建一个新文件夹,用于包含后续所有文件:

mkdir factor
cd factor

2.2 执行new命令:

snarkjs powersoftau new bn128 12 pot12_0000.ptau -v

* 解释:

[new]:用于开启一个新的 powers of tau ceremony (该叫法摘自snarkjs库0.4.6官方教程)

[bn128]:选择bn128曲线(可选的还有bls12-381曲线,bn和bls的简介见后面“补充”部分)

[12]:规定了我们接下来要构建的电路的两个限制。限制1:电路中constraints(稍后会解释)的数量不能多于2^{12}= 4096个;限制2:电路中parameter的数量不能多于2^{28}\approx 268\times 10^{6}个。

* 效果:

此条命令会创建一个pot12_0000.ptau文件,执行命令后会打印以下字段:

* 补充

参考博文zk-SNARK零知识证明曲线选择及Electric Coin Co. 官网的相关内容,Barreto-Naehrig (BN) 和Barreto-Lynn-Scott (BLS)都是pairing-friendly椭圆曲线。不同之处在于,BN曲线若想要达到128-bit的安全性,需要q≈2384,相应的BN曲线的阶数r也会提高到2384量级,r值的增大会影响multi-exponentiation、FFT等运算性能,从而影响zk-SNARK以及安全多方计算的执行效率,同时也会影响key文件不必要的增大。 而对于BLS曲线,当q≈2384 且 embedding degree k=12时,具有128-bit的安全性,而相应的阶数r≈2256,远小于BN曲线的2384量级。

2.3 执行contribute命令

snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau --name="First contribution" -v

* 解释:

[contribute] 该命令将上一步创建的pot12_0000.ptau文件作为输入,并输出一个新的ptau文件pot12_0001.ptau。ptau文件包含所有已经进行过的challenge和response计算。

[name] 这一字段内你可以任意填入一些内容。在后面执行验证(第6步)的时候这个内容会被打印出来。

* 效果:

执行此条命令,会被要求输入一些随机内容,输入后打印如下内容:

2.4 第二次contribute

snarkjs powersoftau contribute pot12_0001.ptau pot12_0002.ptau --name="Second contribution" -v -e="some random text"

* 解释:

此条命令与上一条功能相同,不同点在于,加入了[-e]命令,直接输入了一些随机值(上一步是交互式地输入随机值,这一步直接将随机值写入了命令中)。

* 效果:

2.5 第三次contribute(第三方contribute)

snarkjs powersoftau export challenge pot12_0002.ptau challenge_0003
snarkjs powersoftau challenge contribute bn128 challenge_0003 response_0003 -e="some random text"
snarkjs powersoftau import response pot12_0002.ptau response_0003 pot12_0003.ptau -n="Third contribution name"

不太确定这步跟上两步的异同,但是执行完成后会生成pot12_0003.ptau文件:

2.6 验证

snarkjs powersoftau verify pot12_0003.ptau

如果验证通过,在打印信息的第一行会显示“[INFO] snarkJS: Powers Of tau file OK!” :

2.7 引入random beacon

snarkjs powersoftau beacon pot12_0003.ptau pot12_beacon.ptau 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon"

此条命令会生成一个pot12_beacon.ptau文件。

2.8 生成公开信息

snarkjs powersoftau prepare phase2 pot12_beacon.ptau pot12_final.ptau -v

* 解释:

[prepare phase2]:生成多项式在点\tau、点\alpha \cdot \tau、点\beta \cdot \tau的值的密文。

此命令将pot12_beacon.ptau文件作为输入,生成一个新文件pot12_final.ptau。

2.9 最终验证

snarkjs powersoftau verify pot12_final.ptau

* 解释:

在开始下一步(构建电路)之前,执行一个最终验证。

* 效果:

执行此条命令,部分打印信息如下:

3.  构建电路

我们准备证明的问题是:我们知道数字a和b(秘密),它们相乘得到c(公开值)。

3.1 创建一个circom文件:

vim circuit.circom

文件内容如下:

1. template Multiplier() {
2.    signal private input a;
3.    signal private input b;
4.    signal output c;
5.    c <== a*b;
6. }
7.
8. component main = Multiplier();

* 解释:

2-4行:这个电路有两个private输入信号,即a和b;有一个输出信号,即c。

第5行:输入和输出使用<==运算符进行关联。 在circom中,<==运算符做两件事。 首先是连接信号。 第二个是施加约束。在本例中,我们使用<==c连接到ab,同时将c约束为a * b的值,即电路做的事情是让强制信号 c 为 a*b的值。

第8行:在声明 Multiplier 模板之后, 我们使用名为main的组件实例化它。编译电路时,必须始终有一个名为main的组件。

(对第5行和第8行的解释摘自博文circom与snarkjs经典教程)

3.2 编译电路

circom circuit.circom --r1cs --wasm --sym -v

3.3 用snarkjs查看编译后的电路

snarkjs r1cs info circuit.r1cs

获得如下输出:

3.4 打印constraints

snarkjs r1cs print circuit.r1cs circuit.sym

打印信息如下:

3.5 将电路输出成json格式

snarkjs r1cs export json circuit.r1cs circuit.r1cs.json
cat circuit.r1cs.json

执行这两条语句后会打印json字符串。

4. 生成groth16算法密钥

** 步骤4.2--4.7类似于上文步骤2.3--2.7, 2.9

4.1 设置

snarkjs groth16 setup circuit.r1cs pot12_final.ptau circuit_0000.zkey

* 解释:

此命令生成zkey,即零知识证明密钥,包含证明密钥(proving key)和验证密钥(verification key)。每个电路都单独生成一个zkey,我们可以验证一个zkey是否属于某个电路。

Note that circuit_0000.zkey (the output of the zkey command above) does not include any contributions yet, so it cannot be used in a final circuit.

——摘自snarkjs库0.4.6官方教程

4.2 zkey Contribute

snarkjs zkey contribute circuit_0000.zkey circuit_0001.zkey --name="1st Contributor Name" -v

此命令会生成一个新的circuit_0001.zkey文件,里面包含了一个contribution。这一步会要求输入一些随机内容,如下:

4.3 第二次contribute

snarkjs zkey contribute circuit_0001.zkey circuit_0002.zkey --name="Second contribution Name" -v -e="Another random entropy"

4.4 第三次contribution(第三方contribute)

snarkjs zkey export bellman circuit_0002.zkey  challenge_phase2_0003
snarkjs zkey bellman contribute bn128 challenge_phase2_0003 response_phase2_0003 -e="some random text"
snarkjs zkey import bellman circuit_0002.zkey response_phase2_0003 circuit_0003.zkey -n="Third contribution name"

4.5 验证

snarkjs zkey verify circuit.r1cs pot12_final.ptau circuit_0003.zkey

4.6 引入random beacon

snarkjs zkey beacon circuit_0003.zkey circuit_final.zkey 0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f 10 -n="Final Beacon phase2"

4.7 验证最终zkey

snarkjs zkey verify circuit.r1cs pot12_final.ptau circuit_final.zkey

4.8 输出验证密钥

snarkjs zkey export verificationkey circuit_final.zkey verification_key.json

5. 计算见证(witness)

witness中包含与已知电路所有constraints相匹配的信号,可以理解为问题的答案。在我们的例子中,一个见证包含a、b、c。我们先生成witness,然后再用witness生成零知识证明。

5.1 创建input文件

创建一个json文件:

vim input.json

在json文件中写入如下内容并保存:

{"a": 3, "b": 11}

5.2 运行计算命令

snarkjs wtns calculate circuit.wasm input.json witness.wtns

5.3 检查witness计算有无错误

snarkjs wtns debug circuit.wasm input.json witness.wtns circuit.sym --trigger --get --set

* 效果:

此命令会打印我们输入的a、b以及相应的输出c:

6. 证明与验证

6.1 构建零知识证明

snarkjs groth16 prove circuit_final.zkey witness.wtns proof.json public.json

* 解释:

这一命令生成文件proof.json和public.json,前者包含证明,后者包含公开输入和公开输出。

* 注:

第5步(计算witness)和第6.1步(生成证明)可以合并为一条语句:

snarkjs groth16 fullprove input.json circuit.wasm circuit_final.zkey proof.json public.json

6.2 验证

snarkjs groth16 verify verification_key.json public.json proof.json

* 效果:

若验证成功将打印“OK!”:

ZK-SNARKS | 创建第一个零知识snark电路相关推荐

  1. 在 BSV 上创建你的第一个零知识证明程序

    ZoKrates 是 zkSNARKs 的工具箱,隐藏了零知识证明 (ZKP) 固有的显着复杂性.它为开发人员提供了一种类似于 python 的高级语言来编写他们想要证明的计算问题. 我们扩展了它,使 ...

  2. 一周速递|OpenAI:AI通过看视频学会玩《我的世界》,人类第一块量子尺度电路发布

    『运筹OR帷幄』原创 OpenAI:看了7万小时的游戏视频后AI学会了像人一样玩<我的世界>! 长久以来,研究人员一直在致力于让人工智能学会玩类似<我的世界>一样的开放世界游戏 ...

  3. UE4创建第一人称射击游戏学习教程

    Unreal Engine 4: Create Your Own First-Person Shooter MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言 ...

  4. UE4创建第一人称射击游戏学习教程 Unreal Engine 4: Create Your Own First-Person Shooter

    UE4创建第一人称射击游戏学习教程 本课程包含38节视频课,将逐步指导您完成以下主题: 云桥网络 平台获取课程! 如何创建6种可定制的武器(包括手枪.突击步枪.猎枪.狙击枪.榴弹发射器和火箭发射器) ...

  5. BI之SSAS完整实战教程3 -- 创建第一个多维数据集

    上一篇我们已经完成了数据源的准备工作,现在我们就开始动手,创建第一个多维数据集(Cube). 文章提纲 使用多维数据集向导创建多维数据集 总结Cube设计器简介 维度细化 总结 一.使用向导创建多维数 ...

  6. Android实例开发中如何创建第一个项目(android studio)

    当我们配置好android环境后,如何创建第一个项目,每一项代表了什么意思,这里以Android studio 为例,其他软件如eclipse等是类似的操作 当我们安装好AS后 这里我们选择第一项 其 ...

  7. vue-cli创建第一个项目(用git bash解决上下键移动选择问题)

    vue-cli创建第一个项目(用git bash解决上下键移动选择问题) 参考文章: (1)vue-cli创建第一个项目(用git bash解决上下键移动选择问题) (2)https://www.cn ...

  8. linux创建的kvm无法运行,使用virt-manager运行虚拟机的方法(创建第一个虚拟机)...

    本文将指导你使用Fedora Linux上的Virt Manager来设置虚拟机,使用virt-manager运行虚拟机,我们来创建第一个虚拟机. 介绍QEMU/KVM和Libvirt 与所有其他Li ...

  9. java 区块链使用_使用Java创建第一个区块链

    本系列教程的目的是帮助你了解如何开发区块链技术.在本教程中,我们将: 创建你的第一个非常基础的区块链. 实施简单的工作量证明系统(采矿). 探讨任何的可能性. 我假设你对面向对象编程有基本的了解.值得 ...

最新文章

  1. QLibrary Class Reference(qt加载外部库)
  2. vue饼图组件_vue2.0 自定义 饼状图 (Echarts)组件
  3. 《MySQL——基于位点orGTID的主备切换协议》
  4. pcb天线和纯铜天线_如何简化天线设计?相控阵波束成形IC来助您
  5. 昨天安装复习中遇到的问题小结
  6. SpringCloud Hoxton版微服务- Ribbon实现负载均衡
  7. L1-001 Hello World (5 分)—团体程序设计天梯赛
  8. Ubuntu系统下安装MATLAB2014a
  9. oracle11g数据库登录01017,连接oracle数据库报错ORA-01017、重置用户的密码
  10. HTML5期末大作业:游戏网站设计与实现——基于bootstrap响应式游戏资讯网站制作HTML+CSS+JavaScript
  11. 可见光通信原理及硬件方案
  12. matlab自适应滤波器 LMS算法
  13. 微信小程序毕业设计 基于微信小程序在线考试系统开题报告
  14. 计算机毕业设计php+vue基于微信小程序的房屋租赁小程序
  15. 给应用重新签名,重新签名包
  16. static, const, static const 与 const static
  17. DocuCentre SC2020 打印机连接
  18. 内网穿透远程群晖NAS:使用自定义域名 3/5
  19. 智能驾驶功能软件平台设计规范 第二部分:感知融合功能服务接口
  20. Minecraft神奇玩家不用键盘,行走全部靠骑猪最后通关MC

热门文章

  1. 关于云音乐数据治理的实践与思考
  2. 1546. 和为目标值且不重叠的非空子数组的最大数目-贪心算法
  3. 日薪行-大龄程序员的绝对优势与绝对劣势-反观01
  4. c++使用vector求矩阵的A的逆
  5. 计算机安全模式都进不了系统,win10电脑安全模式都进不去怎么办
  6. 思科交换机等设备基本配置
  7. redis统计用户日活量_使用redis统计用户日活、月活(实践版)
  8. 导师和学生之间应该多说实话
  9. 浅谈音视频开发入门基础及进阶资源分享
  10. DOS命令字典..收藏