铜锁支持 Bulletproofs 算法
背景
零知识证明(ZKP,Zero Knowledge Proof)是隐私计算和区块链领域中非常重要的密码学技术,能够在证明者不向验证者提供任何有用信息的情况下,使验证者相信某个论断是正确的。零知识证明于1985 年提出,至今30多年,但目前主流的零知识证明算法仅有 zk-SNARKs、zk-STARKs 和 Bulletproofs,其中 zk-SNARKs 于 2013 年提出,因其常数级的验证时间和证明大小较小,在区块链中获取了广泛的应用,但其原理非常复杂,生成证明的计算复杂度较高,还需要 trusted-setup,耦合度和复杂度都比较高,在一些场景中并不适用,zk-STARKs 解决了 zk-SNARKs 需要 trusted-setup 的问题,但其生成 zk-STARKs 的证明 size 较大,验证 zk-STARKs 的证明计算复杂度较高,不管是 zk-SNARKs 还是 zk-STARKs,门槛都比较高,而 2018年提出的 Bulletproofs 算法,其设计目标是克服传统方案的缺点并提供更高效、更紧凑的零知识证明方案。它具有以下几个优势:
- 高效性:Bulletproofs 算法具有线性的验证复杂度,这意味着验证一个证明所需的计算量与证明的大小成正比,具有较高的效率。
- 紧凑性:Bulletproofs 生成的证明相对较小,通常是输入规模的对数级别。相比于传统方案,它们更有效地传输和存储,减少了通信和存储成本。这对于在有限的计算和存储资源下进行零知识证明非常有价值。
- 通用性:Bulletproofs 是通用的,可以用于证明范围(range)和证明知识(r1cs)的零知识证明。它可以应用于各种不同的应用场景,包括Web3领域的保密交易、身份验证和隐私保护等。
- 兼容性:Bulletproofs 与现有的区块链技术兼容。它可以与现有的密码学原语和协议配合使用,如零知识范围证明(Range Proof)和加密哈希函数。这使得 Bulletproofs 能够与现有的系统和平台集成,并为其提供更高效和可靠的零知识证明能力。
综上所述,Bulletproofs 的背景是解 决传统零知识证明方案的限制和缺点,它通过提供高效、紧凑和通用的证明方案来解决这些问题。Bulletproofs 具有高效性、紧凑性、通用性和兼容性等优势,使其成为在各种隐私保护和认证应用中广泛使用的零知识证明算法。目前,实现 Bulletproofs 算法的开源项目中,一是稀少,二是质量一般,三是门槛较高。铜锁作为基础密码库,非常有必要实现零知识证明算法,特别是 Bulletproofs 算法,可以将 Bulletproofs 算法应用到更多的领域,解决隐私计算和区块链中的难题。
概念
公共参数
Bulletproofs 的公共参数也有预先设置的过程,但与 zk-SNARKs 的 trusted-setup 有着较大区别,所谓 trusted-setup 是指在协议进行证明和认证之前,需要生成和设置一些公共的参数,但是在生成这些公共参数的过程中,生成了一些不能公开的中间数据,需要在完成 setup 之后把这部分不能公开的数据删除,否则任何一方拿到这些数据都能够破解协议。而 Bulletproofs 的公共参数生成叫做 setup,而不是 trusted-setup,在 Bulletproofs 的公共参数生成过程中,参与者执行特定的计算,并共享生成的公共参数,然后,其他验证者可以使用这些公共参数来验证证明的有效性。所以,证明者和验证者需要在相同的公共参数下进行,否则无法验证通过。 Bulletproofs 的公共参数主要包含两组椭圆曲线上的点,一般表示为 G 和 H,这些点生成的方式各种实现不一样,原则上只要是生成的点是椭圆曲线上的点即可, 铜锁的生成方式是随机选择指定椭圆曲线上的点,而 rust 版本的 Bulletproofs 公共参数生成方式是按特定算法生成椭圆曲线上的点,这两种方式各有优劣,铜锁的生成方式更随机和通用,适应更多场景,但需要分发和共享公共参数,这些公共参数占用几 k 到几十 k 的空间,如果按特定算法生成公共参数可以不需要分发和共享,但所有场景的公共参数都一样的话可能会带来一些安全问题(这个有待考证),后面铜锁再支持按特定算法生成公共参数供用户自行选择。
证据
证据是生成证明的关键输入,证据中包含明文变量(v)和随机数(r),以及由明文变量和随机数加密生成的密文变量(V),Bulletproofs 论文中明确了 V 的计算公式:,这一步叫 Pedersen commitment,其中,证明者用到明文变量(v)和随机数(r),验证者用到密文变量(V),所以证据打包发给验证者时只需要打包密文变量 V 即可。 由于 R1CS 场景中需要将变量转换成线性约束后才能进行算术电路的运算,所以铜锁将变量实现成有名变量,方便证明者和验证者提取相关的线性约束进行算术电路的运算。需要注意的是范围证明(range proof)场景没有可变约束条件这一步,计算时会忽略证据变量中的名字,有名/无名变量都可以。
约束条件
约束条件是 R1CS 的组成部分,这些约束条件规定了输入变量之间的关系,每个约束条件都是一个等式,其中涉及到变量之间的乘法和加法运算,为了简化命令行输入和表达式解析,目前铜锁 bulletproofs 命令行只支持恒等于0的约束条件表达式,涉及到输入变量的简单约束可以在命令行完成,更复杂的逻辑运算(比如比特位判断)需要在代码中使用铜锁提供的 Bulletproofs 线性组合运算接口进行。约束条件表达式中使用的变量名必须在证据中找到提交的有名变量才行,否则报错。 约束条件是证明和验证的重要输入,对于证明者来说,需要使用证据和约束条件来计算生成相应的证明(proof),该约束条件用到的是明文证据 v 和 r,对于验证者来说,需要验证证明在该约束条件下是否有效, 该约束条件用到的是密文证据 V。
证明
证明(prove)是证明者将明文证据和约束条件计算生成一个证明对象(proof)的过程,比如证明者知道两个数 a=5 和 b=25 满足表达式 ,其中约束条件 是 ,a=5 和 b=25 是有名变量,组成明文证据,a 和 b 根据密文证据公式可以计算出密文证据 a=A 和 b=B,其中 A、B 是密文,其变量名字也是 a 和 b,证明者在构造约束条件时使用的有名变量 a 和 b 用到的是明文证据 5 和 25,而验证者在构造约束条件时使用的也是有名变量 a 和 b,但用到的是密文证据 A 和 B,从而达到隐私保护的目的。 证明(prove)的输入是证据(witness)和约束条件(constraint),输出是证明对象(proof)。证明者将 proof 编码后发给验证者,验证者验证该 proof 是否有效。