Groth16 ZKP: 零知识证明

简介 Groth16 是由 Jens Groth 于 2016 年提出的 zk-SNARK 协议。它是目前区块链领域(如 Zcash, Ethereum L2, Filecoin)应用最广泛的算法。

核心特性:

  • 极致简洁 (Succinct) :证明 <math xmlns="http://www.w3.org/1998/Math/MathML"> π \pi </math>π 仅包含 3 个群元素 (在 BN254 曲线下仅约 128-200 字节)。
  • 验证极快 (Fast Verification) :验证过程仅需 3 次双线性配对 (Pairing) 运算。
  • 需要可信设置 (Trusted Setup):需要为每一个电路单独生成 CRS (Common Reference String)。

整体工作流:

  1. 计算逻辑 (Code) <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 算术电路 (Arithmetic Circuit)
  2. 算术电路 <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 一阶约束系统 (R1CS)
  3. R1CS <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 二次算术程序 (QAP)
  4. Groth16 (基于椭圆曲线和配对的证明生成与验证)

第一节:计算逻辑到算术电路 (Logic to Arithmetic Circuit)

1.1 核心概念转换

零知识证明不直接处理计算机程序(如 C++, Python),而是处理数学多项式 。将代码转化为数学形式的第一步是算术化 (Arithmetization)

传统程序 (CPU) 算术电路 (ZKP) 区别核心
指令流 数据流 电路没有寄存器,只有导线连接
动态执行 (Loops, Jumps) 静态拓扑 (Unrolled Loops) 循环必须展开,路径必须固定
布尔运算 (AND, XOR) 有限域算术 (+, <math xmlns="http://www.w3.org/1998/Math/MathML"> × \times </math>×) 位运算极其昂贵,需用多项式模拟

1.2 算术电路的构成

电路定义在有限域 <math xmlns="http://www.w3.org/1998/Math/MathML"> F r \mathbb{F}_r </math>Fr 上(模 <math xmlns="http://www.w3.org/1998/Math/MathML"> p p </math>p 的整数域)。

  • 导线 (Wires):承载数值(Witness)。
  • 加法门 (Addition Gate) : <math xmlns="http://www.w3.org/1998/Math/MathML"> z = x + y z = x + y </math>z=x+y(计算成本极低,甚至视为免费)。
  • 乘法门 (Multiplication Gate) : <math xmlns="http://www.w3.org/1998/Math/MathML"> z = x × y z = x \times y </math>z=x×y(昂贵,决定了生成证明的速度和大小)。

1.3 转换实例:三次方程

假设证明目标:"我知道一个数 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x,使得 <math xmlns="http://www.w3.org/1998/Math/MathML"> x 3 + x + 5 = 35 x^3 + x + 5 = 35 </math>x3+x+5=35"

第一步:拍平 (Flattening)

将复杂的嵌套计算拆解为单一操作符( <math xmlns="http://www.w3.org/1998/Math/MathML"> o p ∈ { + , × } op \in \{+, \times\} </math>op∈{+,×})的序列。引入中间变量 <math xmlns="http://www.w3.org/1998/Math/MathML"> v i v_i </math>vi。

  • 原始逻辑func(x) { return x*x*x + x + 5 == 35 }
  • 拍平后
    1. <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 = x ⋅ x v_1 = x \cdot x </math>v1=x⋅x
    2. <math xmlns="http://www.w3.org/1998/Math/MathML"> v 2 = v 1 ⋅ x v_2 = v_1 \cdot x </math>v2=v1⋅x
    3. <math xmlns="http://www.w3.org/1998/Math/MathML"> o u t = v 2 + x + 5 out = v_2 + x + 5 </math>out=v2+x+5

第二步:构建电路门 (Circuit Gates)

将上述步骤转化为电路约束。每个乘法关系对应一个门。

  1. 乘法门 1 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> M 1 M_1 </math>M1):

    • 左输入: <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x
    • 右输入: <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x
    • 输出: <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 v_1 </math>v1
    • 代数约束 : <math xmlns="http://www.w3.org/1998/Math/MathML"> x ⋅ x − v 1 = 0 x \cdot x - v_1 = 0 </math>x⋅x−v1=0
  2. 乘法门 2 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> M 2 M_2 </math>M2):

    • 左输入: <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 v_1 </math>v1
    • 右输入: <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x
    • 输出: <math xmlns="http://www.w3.org/1998/Math/MathML"> v 2 v_2 </math>v2
    • 代数约束 : <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 ⋅ x − v 2 = 0 v_1 \cdot x - v_2 = 0 </math>v1⋅x−v2=0
  3. 加法/线性组合 (作为最终约束):

    • 约束: <math xmlns="http://www.w3.org/1998/Math/MathML"> ( v 2 + x + 5 ) ⋅ 1 = 35 (v_2 + x + 5) \cdot 1 = 35 </math>(v2+x+5)⋅1=35
    • 注:在 R1CS 中,加法通常融合在 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ⋅ B = C A \cdot B = C </math>A⋅B=C 的线性组合中,不需要单独的门。

1.4 处理复杂逻辑 (Difficulties)

对于非代数运算,必须用数学约束模拟:

  1. 布尔约束 (Boolean Check) : 证明一个变量 <math xmlns="http://www.w3.org/1998/Math/MathML"> b b </math>b 是二进制位(0 或 1)。
    • 公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> b ⋅ ( 1 − b ) = 0 b \cdot (1 - b) = 0 </math>b⋅(1−b)=0
  2. 条件选择 (If-Else / Multiplexer) : 逻辑 if (b) y = x else y = z
    • 公式 : <math xmlns="http://www.w3.org/1998/Math/MathML"> y = b ⋅ x + ( 1 − b ) ⋅ z y = b \cdot x + (1 - b) \cdot z </math>y=b⋅x+(1−b)⋅z
    • 注:必须计算所有分支,通过数学公式"选择"结果。
  3. 位运算 (Bitwise Operations) : 由于域元素 <math xmlns="http://www.w3.org/1998/Math/MathML"> F r \mathbb{F}_r </math>Fr 是大整数,无法直接进行位操作。需要针对单 bit ( <math xmlns="http://www.w3.org/1998/Math/MathML"> a , b ∈ { 0 , 1 } a, b \in \{0,1\} </math>a,b∈{0,1}) 使用代数公式:
    • XOR ( <math xmlns="http://www.w3.org/1998/Math/MathML"> ⊕ \oplus </math>⊕) : <math xmlns="http://www.w3.org/1998/Math/MathML"> a ⊕ b = a + b − 2 a b a \oplus b = a + b - 2ab </math>a⊕b=a+b−2ab
      • 验证 : <math xmlns="http://www.w3.org/1998/Math/MathML"> 0 + 0 = 0 , 1 + 0 = 1 , 1 + 1 − 2 = 0 0+0=0, 1+0=1, 1+1-2=0 </math>0+0=0,1+0=1,1+1−2=0 (正确)
    • AND ( <math xmlns="http://www.w3.org/1998/Math/MathML"> ∧ \land </math>∧) : <math xmlns="http://www.w3.org/1998/Math/MathML"> a ∧ b = a ⋅ b a \land b = a \cdot b </math>a∧b=a⋅b
    • OR ( <math xmlns="http://www.w3.org/1998/Math/MathML"> ∨ \lor </math>∨) : <math xmlns="http://www.w3.org/1998/Math/MathML"> a ∨ b = a + b − a b a \lor b = a + b - ab </math>a∨b=a+b−ab
    • NOT ( <math xmlns="http://www.w3.org/1998/Math/MathML"> ¬ \neg </math>¬) : <math xmlns="http://www.w3.org/1998/Math/MathML"> ¬ a = 1 − a \neg a = 1 - a </math>¬a=1−a
  4. 位分解 (Bit Decomposition) : 若要对 32 位整数 <math xmlns="http://www.w3.org/1998/Math/MathML"> X X </math>X 进行位运算,必须先将其拆解为 32 个变量 <math xmlns="http://www.w3.org/1998/Math/MathML"> b 0 ... b 31 b_0 \dots b_{31} </math>b0...b31,并添加约束:
    • 约束 1 (聚合) : <math xmlns="http://www.w3.org/1998/Math/MathML"> X = ∑ i = 0 31 2 i ⋅ b i X = \sum_{i=0}^{31} 2^i \cdot b_i </math>X=∑i=0312i⋅bi
    • 约束 2 (二进制检查) : 对每个 <math xmlns="http://www.w3.org/1998/Math/MathML"> b i b_i </math>bi 都要约束 <math xmlns="http://www.w3.org/1998/Math/MathML"> b i ( 1 − b i ) = 0 b_i(1-b_i)=0 </math>bi(1−bi)=0。
    • 代价:这就是 SHA-256 等哈希函数在 ZK 中极其昂贵的原因(需要数万个约束)。

1.5 总结

  • 输入:一段代码逻辑。
  • 输出:一张包含输入导线、中间导线、输出导线以及乘法门的"图纸"。
  • Witness :使得电路所有门都成立的一组数值向量(例如 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ 1 , 35 , 3 , 9 , 27 ] [1, 35, 3, 9, 27] </math>[1,35,3,9,27])。

第二节:算术电路到 R1CS (Arithmetic Circuit to R1CS)

2.1 什么是 R1CS (Rank-1 Constraint System)

R1CS 是一组定义在有限域上的特殊方程组。它的核心思想是把电路中的每一个乘法门(以及相关的线性组合)都标准化为同一个数学格式

标准公式: 对于每一个逻辑门 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i,必须满足:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( A i ⋅ s ) × ( B i ⋅ s ) = ( C i ⋅ s ) (\mathbf{A}_i \cdot \mathbf{s}) \times (\mathbf{B}_i \cdot \mathbf{s}) = (\mathbf{C}_i \cdot \mathbf{s}) </math>(Ai⋅s)×(Bi⋅s)=(Ci⋅s)

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s (Solution Vector): 全局变量解向量(Witness)。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> A i , B i , C i \mathbf{A}_i, \mathbf{B}_i, \mathbf{C}_i </math>Ai,Bi,Ci: 系数向量。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> ⋅ \cdot </math>⋅ (Dot Product) : 向量点积,代表对变量进行线性组合(加法)。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> × \times </math>×: 数值乘法。

直译含义 : <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 左输入导线的线性组合 ) × ( 右输入导线的线性组合 ) = ( 输出导线的线性组合 ) (\text{左输入导线的线性组合}) \times (\text{右输入导线的线性组合}) = (\text{输出导线的线性组合}) </math>(左输入导线的线性组合)×(右输入导线的线性组合)=(输出导线的线性组合)

2.2 构建解向量 (The Witness Vector <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s)

为了用矩阵描述电路,首先要将电路中出现过的所有 数值拍平成一个长向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s。 通常结构如下:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> s = [ 1 , Public Outputs , Public Inputs , Private Inputs , Intermediate Variables ] \mathbf{s} = [\ 1, \ \text{Public Outputs}, \ \text{Public Inputs}, \ \text{Private Inputs}, \ \text{Intermediate Variables} \ ] </math>s=[ 1, Public Outputs, Public Inputs, Private Inputs, Intermediate Variables ]

  • 常数 1 : 必须包含,用于处理加法中的常数项(如 <math xmlns="http://www.w3.org/1998/Math/MathML"> x + 5 x+5 </math>x+5 中的 5,即 <math xmlns="http://www.w3.org/1998/Math/MathML"> 5 × 1 5 \times 1 </math>5×1)。

实例 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> x 3 + x + 5 = 35 x^3+x+5=35 </math>x3+x+5=35) 的向量定义 : 假设变量顺序为 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ o n e , o u t , x , v 1 , v 2 ] [one, out, x, v_1, v_2] </math>[one,out,x,v1,v2],若 <math xmlns="http://www.w3.org/1998/Math/MathML"> x = 3 x=3 </math>x=3,则:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> s = [ 1 , 35 , 3 , 9 , 27 ] \mathbf{s} = [\ 1, \ 35, \ 3, \ 9, \ 27 \ ] </math>s=[ 1, 35, 3, 9, 27 ]

2.3 门到约束的转换 (Gate to Constraints)

我们需要为电路中的每一步运算构建 <math xmlns="http://www.w3.org/1998/Math/MathML"> a , b , c \mathbf{a}, \mathbf{b}, \mathbf{c} </math>a,b,c 三个系数向量。

回顾逻辑:

  1. <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 = x ⋅ x v_1 = x \cdot x </math>v1=x⋅x
  2. <math xmlns="http://www.w3.org/1998/Math/MathML"> v 2 = v 1 ⋅ x v_2 = v_1 \cdot x </math>v2=v1⋅x
  3. <math xmlns="http://www.w3.org/1998/Math/MathML"> o u t = ( v 2 + x + 5 ) ⋅ 1 out = (v_2 + x + 5) \cdot 1 </math>out=(v2+x+5)⋅1 (加法通过乘以常数 1 转化为乘法约束)

约束 1: <math xmlns="http://www.w3.org/1998/Math/MathML"> x ⋅ x = v 1 x \cdot x = v_1 </math>x⋅x=v1

  • 左输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x (向量第 3 位)。 <math xmlns="http://www.w3.org/1998/Math/MathML"> a 1 = [ 0 , 0 , 1 , 0 , 0 ] \mathbf{a}_1 = [0, 0, 1, 0, 0] </math>a1=[0,0,1,0,0]
  • 右输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x (向量第 3 位)。 <math xmlns="http://www.w3.org/1998/Math/MathML"> b 1 = [ 0 , 0 , 1 , 0 , 0 ] \mathbf{b}_1 = [0, 0, 1, 0, 0] </math>b1=[0,0,1,0,0]
  • 输出 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 v_1 </math>v1 (向量第 4 位)。 <math xmlns="http://www.w3.org/1998/Math/MathML"> c 1 = [ 0 , 0 , 0 , 1 , 0 ] \mathbf{c}_1 = [0, 0, 0, 1, 0] </math>c1=[0,0,0,1,0]
  • 验证 : <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 1 ⋅ x ) × ( 1 ⋅ x ) = v 1 (1\cdot x) \times (1\cdot x) = v_1 </math>(1⋅x)×(1⋅x)=v1

约束 2: <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 ⋅ x = v 2 v_1 \cdot x = v_2 </math>v1⋅x=v2

  • 左输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> v 1 v_1 </math>v1。 <math xmlns="http://www.w3.org/1998/Math/MathML"> a 2 = [ 0 , 0 , 0 , 1 , 0 ] \mathbf{a}_2 = [0, 0, 0, 1, 0] </math>a2=[0,0,0,1,0]
  • 右输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x。 <math xmlns="http://www.w3.org/1998/Math/MathML"> b 2 = [ 0 , 0 , 1 , 0 , 0 ] \mathbf{b}_2 = [0, 0, 1, 0, 0] </math>b2=[0,0,1,0,0]
  • 输出 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> v 2 v_2 </math>v2。 <math xmlns="http://www.w3.org/1998/Math/MathML"> c 2 = [ 0 , 0 , 0 , 0 , 1 ] \mathbf{c}_2 = [0, 0, 0, 0, 1] </math>c2=[0,0,0,0,1]
  • 验证 : <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 1 ⋅ v 1 ) × ( 1 ⋅ x ) = v 2 (1\cdot v_1) \times (1\cdot x) = v_2 </math>(1⋅v1)×(1⋅x)=v2

约束 3: <math xmlns="http://www.w3.org/1998/Math/MathML"> ( v 2 + x + 5 ) ⋅ 1 = o u t (v_2 + x + 5) \cdot 1 = out </math>(v2+x+5)⋅1=out

这是一次利用 R1CS 特性处理加法的操作。

  • 左输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A) : 线性组合 <math xmlns="http://www.w3.org/1998/Math/MathML"> v 2 + x + 5 v_2 + x + 5 </math>v2+x+5。
    • 5 对应常数项 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> 5 × s [ 0 ] 5 \times \mathbf{s}[0] </math>5×s[0])。
    • <math xmlns="http://www.w3.org/1998/Math/MathML"> a 3 = [ 5 , 0 , 1 , 0 , 1 ] \mathbf{a}_3 = [5, 0, 1, 0, 1] </math>a3=[5,0,1,0,1]
  • 右输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B) : 常数 1。
    • <math xmlns="http://www.w3.org/1998/Math/MathML"> b 3 = [ 1 , 0 , 0 , 0 , 0 ] \mathbf{b}_3 = [1, 0, 0, 0, 0] </math>b3=[1,0,0,0,0]
  • 输出 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C) : 取 <math xmlns="http://www.w3.org/1998/Math/MathML"> o u t out </math>out。
    • <math xmlns="http://www.w3.org/1998/Math/MathML"> c 3 = [ 0 , 1 , 0 , 0 , 0 ] \mathbf{c}_3 = [0, 1, 0, 0, 0] </math>c3=[0,1,0,0,0]
  • 验证 : <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 5 + x + v 2 ) × 1 = o u t (5 + x + v_2) \times 1 = out </math>(5+x+v2)×1=out

2.4 矩阵形式 (Matrix Representation)

将所有约束的向量堆叠起来,形成三个矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B , C A, B, C </math>A,B,C。 假设电路有 <math xmlns="http://www.w3.org/1998/Math/MathML"> m m </math>m 个门,解向量长度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> n n </math>n。矩阵维度为 <math xmlns="http://www.w3.org/1998/Math/MathML"> m × n m \times n </math>m×n。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> A = [ 0 0 1 0 0 0 0 0 1 0 5 0 1 0 1 ] , B = [ 0 0 1 0 0 0 0 1 0 0 1 0 0 0 0 ] , C = [ 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 ] A = \begin{bmatrix} 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 5 & 0 & 1 & 0 & 1 \end{bmatrix}, \quad B = \begin{bmatrix} 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 & 0 \\ 1 & 0 & 0 & 0 & 0 \end{bmatrix}, \quad C = \begin{bmatrix} 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 0 & 1 \\ 0 & 1 & 0 & 0 & 0 \end{bmatrix} </math>A= 005000101010001 ,B= 001000110000000 ,C= 000001000100010

R1CS 系统定义 : 对于给定的公开输入和私有 Witness 组成的向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s,如果它是合法的,则必须满足:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ( A ⋅ s ) ∘ ( B ⋅ s ) = ( C ⋅ s ) (A \cdot \mathbf{s}) \circ (B \cdot \mathbf{s}) = (C \cdot \mathbf{s}) </math>(A⋅s)∘(B⋅s)=(C⋅s)

( <math xmlns="http://www.w3.org/1998/Math/MathML"> ∘ \circ </math>∘ 代表阿达玛乘积,即逐元素相乘)

2.5 总结

  • 输入:算术电路图。
  • 输出 :三个稀疏矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B , C A, B, C </math>A,B,C。
  • 意义:将复杂的程序逻辑,彻底转化为了线性代数问题(矩阵运算)。
  • 下一步:矩阵是离散的,为了能进行极简验证(Probabilistic Check),我们需要通过多项式插值将其转化为连续形式(QAP)。

第三节:R1CS 到 QAP (R1CS to QAP)

3.1 核心目标

R1CS 虽然严谨,但验证成本很高:如果有 100 万个约束(矩阵有 100 万行),验证者就需要逐行检查。 QAP (Quadratic Arithmetic Program) 的目标是将这 <math xmlns="http://www.w3.org/1998/Math/MathML"> m m </math>m 个离散的约束方程 ,打包成 1 个连续的多项式方程

变换逻辑

  • 矩阵的行 (Rows) <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 多项式的求值点 (Evaluation Points)
  • 矩阵的列 (Columns) <math xmlns="http://www.w3.org/1998/Math/MathML"> → \rightarrow </math>→ 基多项式 (Basis Polynomials)

3.2 拉格朗日插值 (Lagrange Interpolation)

这是实现变换的数学工具。它的作用是找到一个多项式,使其穿过所有指定的坐标点。

变换过程

  1. 定义根 (Roots) :为 R1CS 的每一行(每一个约束门)分配一个索引值 <math xmlns="http://www.w3.org/1998/Math/MathML"> r k r_k </math>rk。
    • 理论上 :可以是 <math xmlns="http://www.w3.org/1998/Math/MathML"> { 1 , 2 , 3 , ... , m } \{1, 2, 3, \dots, m\} </math>{1,2,3,...,m}。
    • 工程上 :为了利用 FFT 加速,使用 单位根 (Roots of Unity) <math xmlns="http://www.w3.org/1998/Math/MathML"> { 1 , ω , ω 2 , ... , ω m − 1 } \{1, \omega, \omega^2, \dots, \omega^{m-1}\} </math>{1,ω,ω2,...,ωm−1}。
  2. 列变换 : 对于矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 的每一列 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i(对应第 <math xmlns="http://www.w3.org/1998/Math/MathML"> i i </math>i 个变量),我们构造一个多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> u i ( x ) u_i(x) </math>ui(x),使得在第 <math xmlns="http://www.w3.org/1998/Math/MathML"> k k </math>k 行,多项式的值等于矩阵该位置的元素值。 <math xmlns="http://www.w3.org/1998/Math/MathML"> u i ( r k ) = A k , i u_i(r_k) = A_{k,i} </math>ui(rk)=Ak,i 同理构造 <math xmlns="http://www.w3.org/1998/Math/MathML"> v i ( x ) v_i(x) </math>vi(x) 对应矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B, <math xmlns="http://www.w3.org/1998/Math/MathML"> w i ( x ) w_i(x) </math>wi(x) 对应矩阵 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C。

3.3 构造 QAP 多项式

一旦有了基多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> { u i ( x ) , v i ( x ) , w i ( x ) } \{u_i(x), v_i(x), w_i(x)\} </math>{ui(x),vi(x),wi(x)},我们将解向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s 中的数值(Witness)作为系数进行线性组合。

定义三个全局多项式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> U ( x ) = ∑ i = 0 n s i ⋅ u i ( x ) U(x) = \sum_{i=0}^n s_i \cdot u_i(x) </math>U(x)=i=0∑nsi⋅ui(x)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> V ( x ) = ∑ i = 0 n s i ⋅ v i ( x ) V(x) = \sum_{i=0}^n s_i \cdot v_i(x) </math>V(x)=i=0∑nsi⋅vi(x)
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> W ( x ) = ∑ i = 0 n s i ⋅ w i ( x ) W(x) = \sum_{i=0}^n s_i \cdot w_i(x) </math>W(x)=i=0∑nsi⋅wi(x)

  • 含义 : <math xmlns="http://www.w3.org/1998/Math/MathML"> U ( x ) U(x) </math>U(x) 代表了在任意 <math xmlns="http://www.w3.org/1998/Math/MathML"> x x </math>x 点,电路左输入导线的加权总和。

3.4 目标多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> t ( x ) t(x) </math>t(x) (The Target Polynomial)

这是一个系统预设的公有多项式,它的根就是所有约束行的索引。 如果使用单位根,它具有极其简洁的形式:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> t ( x ) = ∏ k = 0 m − 1 ( x − ω k ) = x m − 1 t(x) = \prod_{k=0}^{m-1} (x - \omega^k) = x^m - 1 </math>t(x)=k=0∏m−1(x−ωk)=xm−1

它的零点恰好就是我们需要检查约束的所有位置。

3.5 QAP 核心方程与整除性

这是整个转换的终点。 如果 Witness <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s 是正确的,那么在所有的约束点 <math xmlns="http://www.w3.org/1998/Math/MathML"> x ∈ { r 0 , ... , r m − 1 } x \in \{r_0, \dots, r_{m-1}\} </math>x∈{r0,...,rm−1} 上,都有:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> U ( x ) ⋅ V ( x ) − W ( x ) = 0 U(x) \cdot V(x) - W(x) = 0 </math>U(x)⋅V(x)−W(x)=0

根据因式定理 (Factor Theorem) ,如果多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> P ( x ) = U ( x ) V ( x ) − W ( x ) P(x) = U(x)V(x) - W(x) </math>P(x)=U(x)V(x)−W(x) 在所有根处都为 0,那么它一定能被 <math xmlns="http://www.w3.org/1998/Math/MathML"> t ( x ) t(x) </math>t(x) 整除。 因此,必然存在一个商多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> H ( x ) H(x) </math>H(x) 使得:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> U ( x ) ⋅ V ( x ) − W ( x ) = H ( x ) ⋅ t ( x ) U(x) \cdot V(x) - W(x) = H(x) \cdot t(x) </math>U(x)⋅V(x)−W(x)=H(x)⋅t(x)

3.6 为什么叫"二次" (Quadratic)?

虽然多项式的阶数(Degree)很高(取决于电路规模 <math xmlns="http://www.w3.org/1998/Math/MathML"> m m </math>m),但约束关系的代数结构是: <math xmlns="http://www.w3.org/1998/Math/MathML"> ( 线性组合 ) × ( 线性组合 ) − ( 线性组合 ) = 0 (\text{线性组合}) \times (\text{线性组合}) - (\text{线性组合}) = 0 </math>(线性组合)×(线性组合)−(线性组合)=0 这在代数定义上属于二次约束 (Quadratic Constraint)。这是双线性配对(只能做一次乘法)所能验证的极限。

3.7 总结

  • 输入 :R1CS 矩阵和解向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> s \mathbf{s} </math>s。
  • 输出 :一组多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> U ( x ) , V ( x ) , W ( x ) , H ( x ) U(x), V(x), W(x), H(x) </math>U(x),V(x),W(x),H(x) 和目标 <math xmlns="http://www.w3.org/1998/Math/MathML"> t ( x ) t(x) </math>t(x)。
  • 核心优势 : 验证者不再需要检查 100 万个方程。根据 Schwartz-Zippel 引理 ,验证者只需要随机挑选一个点 <math xmlns="http://www.w3.org/1998/Math/MathML"> τ \tau </math>τ,检查 <math xmlns="http://www.w3.org/1998/Math/MathML"> U ( τ ) V ( τ ) − W ( τ ) = ? H ( τ ) t ( τ ) U(\tau)V(\tau) - W(\tau) \overset{?}{=} H(\tau)t(\tau) </math>U(τ)V(τ)−W(τ)=?H(τ)t(τ) 是否成立。
    • 如果在这个随机点成立,那么整个多项式在全域相等的概率接近 100%。
    • 这就是 zk-SNARKs "Succinct"(简洁)特性的来源。

第四节:Groth16 原理 (Groth16 Protocol over QAP)

4.1 核心数学工具

Groth16 建立在椭圆曲线对 (Elliptic Curve Pairings) 之上。

  • 群结构 : 定义三个循环群 <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 , G 2 , G T G_1, G_2, G_T </math>G1,G2,GT,阶为质数 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r。生成元分别为 <math xmlns="http://www.w3.org/1998/Math/MathML"> g ∈ G 1 , h ∈ G 2 g \in G_1, h \in G_2 </math>g∈G1,h∈G2。
  • 符号 : <math xmlns="http://www.w3.org/1998/Math/MathML"> [ x ] 1 = x ⋅ g [x]_1 = x \cdot g </math>[x]1=x⋅g, <math xmlns="http://www.w3.org/1998/Math/MathML"> [ x ] 2 = x ⋅ h [x]_2 = x \cdot h </math>[x]2=x⋅h。
  • 双线性配对 (Bilinear Pairing) : 映射 <math xmlns="http://www.w3.org/1998/Math/MathML"> e : G 1 × G 2 → G T e: G_1 \times G_2 \rightarrow G_T </math>e:G1×G2→GT。
    • 关键性质: <math xmlns="http://www.w3.org/1998/Math/MathML"> e ( [ a ] 1 , [ b ] 2 ) = e ( [ 1 ] 1 , [ 1 ] 2 ) a b e([a]_1, [b]_2) = e([1]_1, [1]_2)^{ab} </math>e([a]1,[b]2)=e([1]1,[1]2)ab。这使得我们可以验证加密数据的乘法关系。

4.2 第一步:可信设置 (Trusted Setup)

为了生成 CRS (Common Reference String),必须采样一组随机数(有毒废料),并在生成密钥后销毁。

随机采样 : <math xmlns="http://www.w3.org/1998/Math/MathML"> α , β , γ , δ , τ ∈ F r ∗ \alpha, \beta, \gamma, \delta, \tau \in \mathbb{F}_r^* </math>α,β,γ,δ,τ∈Fr∗。

生成密钥:

  1. 验证密钥 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> v k vk </math>vk): 用于处理公开输入和最终检查。

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> v k = ( [ α ] 1 , [ β ] 2 , [ γ ] 2 , [ δ ] 2 , { [ β u i ( τ ) + α v i ( τ ) + w i ( τ ) γ ] 1 } i = 0 l ) vk = \left( [\alpha]_1, [\beta]_2, [\gamma]_2, [\delta]_2, \{ [\frac{\beta u_i(\tau) + \alpha v_i(\tau) + w_i(\tau)}{\gamma}]1 \}{i=0}^l \right) </math>vk=([α]1,[β]2,[γ]2,[δ]2,{[γβui(τ)+αvi(τ)+wi(τ)]1}i=0l)

    • 最后一项是针对公开输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> i = 0 ... l i=0 \dots l </math>i=0...l) 的预计算。
  2. 证明密钥 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk) : 必须包含生成 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B , C A, B, C </math>A,B,C 所需的所有群元素。

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> p k = ( [ α ] 1 , [ β ] 1 , [ δ ] 1 ⏟ G1 常数 , { [ τ i ] 1 } i = 0 d − 1 ⏟ G1 幂次 , { [ β u i ( τ ) + α v i ( τ ) + w i ( τ ) δ ] 1 } i = l + 1 m ⏟ G1 私有 Witness , { [ τ i t ( τ ) δ ] 1 } i = 0 d − 2 ⏟ G1 H项 , [ β ] 2 , [ δ ] 2 ⏟ G2 常数 , { [ τ i ] 2 } i = 0 d − 1 ⏟ G2 幂次 ) pk = \left( \underbrace{[\alpha]1, [\beta]1, [\delta]1}{\text{G1 常数}}, \underbrace{\{ [\tau^i]1 \}{i=0}^{d-1}}{\text{G1 幂次}}, \underbrace{\{ [\frac{\beta u_i(\tau) + \alpha v_i(\tau) + w_i(\tau)}{\delta}]1 \}{i=l+1}^m}{\text{G1 私有 Witness}}, \underbrace{\{ [\frac{\tau^i t(\tau)}{\delta}]1 \}{i=0}^{d-2}}_{\text{G1 H项}}, \underbrace{[\beta]2, [\delta]2}{\text{G2 常数}}, \underbrace{\{ [\tau^i]2 \}{i=0}^{d-1}}{\text{G2 幂次}} \right) </math>pk= G1 常数 [α]1,[β]1,[δ]1,G1 幂次 {[τi]1}i=0d−1,G1 私有 Witness {[δβui(τ)+αvi(τ)+wi(τ)]1}i=l+1m,G1 H项 {[δτit(τ)]1}i=0d−2,G2 常数 [β]2,[δ]2,G2 幂次 {[τi]2}i=0d−1

    • 注: <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk 必须包含 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ β ] 1 [\beta]_1 </math>[β]1 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> { [ τ i ] 2 } \{[\tau^i]_2\} </math>{[τi]2} 才能完成 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B 的计算。

4.3 第二步:证明生成 (Proving)

证明者拥有 Witness <math xmlns="http://www.w3.org/1998/Math/MathML"> a = { a 0 , ... , a m } \mathbf{a} = \{a_0, \dots, a_m\} </math>a={a0,...,am},满足 QAP 方程 <math xmlns="http://www.w3.org/1998/Math/MathML"> U ( x ) V ( x ) − W ( x ) = h ( x ) t ( x ) U(x)V(x) - W(x) = h(x)t(x) </math>U(x)V(x)−W(x)=h(x)t(x)。 为了实现零知识,证明者采样随机数 <math xmlns="http://www.w3.org/1998/Math/MathML"> r , s ∈ F r r, s \in \mathbb{F}_r </math>r,s∈Fr。

构造 <math xmlns="http://www.w3.org/1998/Math/MathML"> π = ( [ A ] 1 , [ B ] 2 , [ C ] 1 ) \pi = ([A]_1, [B]_2, [C]_1) </math>π=([A]1,[B]2,[C]1):

  1. 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A ( <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 G_1 </math>G1 群):

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> A = [ α ] 1 + ∑ i = 0 m a i u i ( τ ) [ 1 ] 1 + r [ δ ] 1 A = [\alpha]1 + \sum{i=0}^m a_i u_i(\tau)[1]_1 + r[\delta]_1 </math>A=[α]1+i=0∑maiui(τ)[1]1+r[δ]1

    • 意义: 对 <math xmlns="http://www.w3.org/1998/Math/MathML"> U ( τ ) U(\tau) </math>U(τ) 的加密评估,加上 <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α 偏移和 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r 混淆。
  2. 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B ( <math xmlns="http://www.w3.org/1998/Math/MathML"> G 2 G_2 </math>G2 群):

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> B = [ β ] 2 + ∑ i = 0 m a i v i ( τ ) [ 1 ] 2 + s [ δ ] 2 B = [\beta]2 + \sum{i=0}^m a_i v_i(\tau)[1]_2 + s[\delta]_2 </math>B=[β]2+i=0∑maivi(τ)[1]2+s[δ]2

    • 意义: 对 <math xmlns="http://www.w3.org/1998/Math/MathML"> V ( τ ) V(\tau) </math>V(τ) 的加密评估,加上 <math xmlns="http://www.w3.org/1998/Math/MathML"> β \beta </math>β 偏移和 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s 混淆。
  3. 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C ( <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 G_1 </math>G1 群 - 核心推导) : 为了满足配对等式,需根据 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ⋅ B A \cdot B </math>A⋅B 的展开式构造 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C。

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> C = ∑ i = l + 1 m a i [ β u i ( τ ) + α v i ( τ ) + w i ( τ ) δ ] 1 + [ h ( τ ) t ( τ ) δ ] 1 ⏟ 利用 pk 计算私有部分 + A s + B r − r s δ ⏟ 平衡随机项 C = \underbrace{\sum_{i=l+1}^m a_i \left[\frac{\beta u_i(\tau) + \alpha v_i(\tau) + w_i(\tau)}{\delta}\right]1 + \left[\frac{h(\tau)t(\tau)}{\delta}\right]1}{\text{利用 pk 计算私有部分}} + \underbrace{As + Br - rs\delta}{\text{平衡随机项}} </math>C=利用 pk 计算私有部分 i=l+1∑mai[δβui(τ)+αvi(τ)+wi(τ)]1+[δh(τ)t(τ)]1+平衡随机项 As+Br−rsδ

    • 注意 : 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> B r Br </math>Br 时需要用到 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk 中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ β ] 1 [\beta]_1 </math>[β]1 以及 <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 G_1 </math>G1 上的 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ V ( τ ) ] 1 [V(\tau)]_1 </math>[V(τ)]1。

4.4 第三步:验证 (Verification)

验证者接收 <math xmlns="http://www.w3.org/1998/Math/MathML"> π = ( A , B , C ) \pi = (A, B, C) </math>π=(A,B,C) 和公开输入 <math xmlns="http://www.w3.org/1998/Math/MathML"> a p u b = { a 1 , ... , a l } \mathbf{a}_{pub} = \{a_1, \dots, a_l\} </math>apub={a1,...,al}。

  1. 计算公开输入项 <math xmlns="http://www.w3.org/1998/Math/MathML"> [ L p u b ] 1 [L_{pub}]_1 </math>[Lpub]1:

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> [ L p u b ] 1 = ∑ i = 0 l a i [ β u i ( τ ) + α v i ( τ ) + w i ( τ ) γ ] 1 [L_{pub}]1 = \sum{i=0}^l a_i \left[ \frac{\beta u_i(\tau) + \alpha v_i(\tau) + w_i(\tau)}{\gamma} \right]_1 </math>[Lpub]1=i=0∑lai[γβui(τ)+αvi(τ)+wi(τ)]1

  2. 执行配对检查:

    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> e ( A , B ) = ? e ( α , β ) ⋅ e ( L p u b , γ ) ⋅ e ( C , δ ) e(A, B) \overset{?}{=} e(\alpha, \beta) \cdot e(L_{pub}, \gamma) \cdot e(C, \delta) </math>e(A,B)=?e(α,β)⋅e(Lpub,γ)⋅e(C,δ)

4.5 严谨性推导:为什么等式成立?

将验证等式右边 (RHS) 的指数部分展开,证明其等于 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ⋅ B A \cdot B </math>A⋅B。

RHS 展开:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> RHS = α β + L p u b γ + C δ \text{RHS} = \alpha\beta + L_{pub}\gamma + C\delta </math>RHS=αβ+Lpubγ+Cδ

代入 <math xmlns="http://www.w3.org/1998/Math/MathML"> L p u b L_{pub} </math>Lpub 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C 的定义(忽略群同构,看作代数):
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> = α β + ∑ i = 0 l a i ( β u i + α v i + w i ) ⏟ 公开部分 + ( ∑ i = l + 1 m a i ( β u i + α v i + w i ) + h t ) ⏟ 私有部分 + δ ( A s + B r − r s δ ) = \alpha\beta + \underbrace{\sum_{i=0}^l a_i(\beta u_i + \alpha v_i + w_i)}{\text{公开部分}} + \underbrace{\left( \sum{i=l+1}^m a_i(\beta u_i + \alpha v_i + w_i) + ht \right)}_{\text{私有部分}} + \delta(As + Br - rs\delta) </math>=αβ+公开部分 i=0∑lai(βui+αvi+wi)+私有部分 (i=l+1∑mai(βui+αvi+wi)+ht)+δ(As+Br−rsδ)

合并公开和私有部分的求和 <math xmlns="http://www.w3.org/1998/Math/MathML"> ∑ i = 0 m \sum_{i=0}^m </math>∑i=0m:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> = α β + ( β U ( τ ) + α V ( τ ) + W ( τ ) ) + h ( τ ) t ( τ ) + δ ( A s + B r − r s δ ) = \alpha\beta + (\beta U(\tau) + \alpha V(\tau) + W(\tau)) + h(\tau)t(\tau) + \delta(As + Br - rs\delta) </math>=αβ+(βU(τ)+αV(τ)+W(τ))+h(τ)t(τ)+δ(As+Br−rsδ)

利用 QAP 核心关系 <math xmlns="http://www.w3.org/1998/Math/MathML"> W + h t = U V W + ht = UV </math>W+ht=UV:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> = α β + β U + α V + U V + δ ( A s + B r − r s δ ) = \alpha\beta + \beta U + \alpha V + UV + \delta(As + Br - rs\delta) </math>=αβ+βU+αV+UV+δ(As+Br−rsδ)

这正是 <math xmlns="http://www.w3.org/1998/Math/MathML"> A ⋅ B = ( α + U + r δ ) ( β + V + s δ ) A \cdot B = (\alpha + U + r\delta)(\beta + V + s\delta) </math>A⋅B=(α+U+rδ)(β+V+sδ) 的展开形式。

4.6 参数作用总结

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> τ \tau </math>τ: 多项式求值的秘密坐标,保证计算基于 QAP。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> α , β \alpha, \beta </math>α,β : 强制 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 和 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B 包含特定的线性结构,确保 <math xmlns="http://www.w3.org/1998/Math/MathML"> U V UV </math>UV 乘积被正确构造。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> γ \gamma </math>γ : 绑定公开输入 。验证者必须使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> v k vk </math>vk 中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> γ \gamma </math>γ 项,无法篡改 Public Input。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> δ \delta </math>δ : 绑定私有 Witness 。证明者必须使用 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk 中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> δ \delta </math>δ 项构造 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C,无法篡改 Private Witness。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> r , s r, s </math>r,s : 提供零知识性 ,使 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B A, B </math>A,B 的分布随机化,隐藏真实的 <math xmlns="http://www.w3.org/1998/Math/MathML"> U , V U, V </math>U,V 值。

第五节:实战演练------Keyless Account (Google OIDC) 认证原理

场景目标 : 用户拥有一份由 Google 签发的 JWT (JSON Web Token) ,其中包含 Google 的 RSA 签名。用户想向区块链合约证明:"我是这个 JWT 的拥有者,且这个 JWT 授权了当前交易使用的临时公钥 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> p k e p h pk_{eph} </math>pkeph),但我不想把 JWT 原始内容暴露在链上。"


5.1 初始状态:输入数据 (Inputs)

在将数据喂给 Groth16 之前,我们需要将业务数据转化为有限域 <math xmlns="http://www.w3.org/1998/Math/MathML"> F r \mathbb{F}_r </math>Fr 上的向量。

A. 解向量 (Witness Vector <math xmlns="http://www.w3.org/1998/Math/MathML"> a \mathbf{a} </math>a)

假设电路已经过 R1CS 转换。向量 <math xmlns="http://www.w3.org/1998/Math/MathML"> a \mathbf{a} </math>a 包含所有输入变量:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> a = [ a p u b ∣ a p r i v ] \mathbf{a} = [\ \mathbf{a}{pub} \ | \ \mathbf{a}{priv} \ ] </math>a=[ apub ∣ apriv ]

1. 公开输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> a p u b \mathbf{a}_{pub} </math>apub - 链上合约已知):

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ 0 ] = 1 \mathbf{a}[0] = 1 </math>a[0]=1 (常数项)
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ 1 ] = Hash ( p k e p h , salt_commitment ) \mathbf{a}[1] = \text{Hash}(pk_{eph}, \text{salt\_commitment}) </math>a[1]=Hash(pkeph,salt_commitment) (Nonce/临时公钥指纹)
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ 2 ] = Hash ( P K G o o g l e ) \mathbf{a}[2] = \text{Hash}(PK_{Google}) </math>a[2]=Hash(PKGoogle) (Google 公钥指纹)

2. 私有输入 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> a p r i v \mathbf{a}_{priv} </math>apriv - 用户本地持有):

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ 3 ... k ] \mathbf{a}[3 \dots k] </math>a[3...k]: JWT Header & Payload (包含用户的 Google ID, iss, aud 等)
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ k + 1 ... m ] \mathbf{a}[k+1 \dots m] </math>a[k+1...m]: RSA Signature (Google 对 JWT 的 2048 位数字签名)
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> a [ m + 1 ] \mathbf{a}[m+1] </math>a[m+1]: Salt (用户隐私盐值)

B. 电路逻辑 (The Circuit Logic)

这个电路包含成千上万个乘法门(主要是 RSA 模幂运算),但核心逻辑可以简化为两个超级约束:

  1. 验签约束 : <math xmlns="http://www.w3.org/1998/Math/MathML"> RSA_Verify ( Payload , Signature , P K G o o g l e ) = = True \text{RSA\Verify}(\text{Payload}, \text{Signature}, PK{Google}) == \text{True} </math>RSA_Verify(Payload,Signature,PKGoogle)==True
  2. 绑定约束 : <math xmlns="http://www.w3.org/1998/Math/MathML"> Payload.nonce = = Hash ( p k e p h , Salt ) \text{Payload.nonce} == \text{Hash}(pk_{eph}, \text{Salt}) </math>Payload.nonce==Hash(pkeph,Salt)

5.2 证明生成 (Prover's Computation - Off-Chain)

用户在本地(浏览器/App)生成证明。他拥有 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk (Proving Key) 和完整的 Witness <math xmlns="http://www.w3.org/1998/Math/MathML"> a \mathbf{a} </math>a。 为了实现零知识(隐藏 Signature 和 Salt),用户选择随机数 <math xmlns="http://www.w3.org/1998/Math/MathML"> r , s ∈ F r r, s \in \mathbb{F}_r </math>r,s∈Fr。

1. 计算多项式快照

用户将 <math xmlns="http://www.w3.org/1998/Math/MathML"> a \mathbf{a} </math>a 代入基多项式,在秘密点 <math xmlns="http://www.w3.org/1998/Math/MathML"> τ \tau </math>τ 处求值(实际上是通过 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk 中的椭圆曲线点进行线性组合):

  • <math xmlns="http://www.w3.org/1998/Math/MathML"> U J W T ( τ ) U_{JWT}(\tau) </math>UJWT(τ): 代表 JWT 数据和 RSA 签名的多项式总和。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> V J W T ( τ ) V_{JWT}(\tau) </math>VJWT(τ): 对应于电路逻辑的右输入总和。
  • <math xmlns="http://www.w3.org/1998/Math/MathML"> W J W T ( τ ) W_{JWT}(\tau) </math>WJWT(τ): 对应于电路逻辑的输出总和。

逻辑正确性保证 : 因为用户的 JWT 签名是真的,且 Nonce 匹配,所以必定存在商多项式 <math xmlns="http://www.w3.org/1998/Math/MathML"> H ( x ) H(x) </math>H(x) 使得: <math xmlns="http://www.w3.org/1998/Math/MathML"> U J W T ( τ ) ⋅ V J W T ( τ ) − W J W T ( τ ) = H ( τ ) t ( τ ) U_{JWT}(\tau) \cdot V_{JWT}(\tau) - W_{JWT}(\tau) = H(\tau)t(\tau) </math>UJWT(τ)⋅VJWT(τ)−WJWT(τ)=H(τ)t(τ)

2. 生成加密点 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B , C A, B, C </math>A,B,C

用户利用 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k pk </math>pk 计算出三个混淆后的点:

  • 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A (在 <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 G_1 </math>G1) : <math xmlns="http://www.w3.org/1998/Math/MathML"> A = [ α ] 1 + [ U J W T ( τ ) ] 1 + r [ δ ] 1 A = [\alpha]1 + [U{JWT}(\tau)]_1 + r[\delta]_1 </math>A=[α]1+[UJWT(τ)]1+r[δ]1

    • 隐喻 : 这里面包含了用户的 RSA 签名 信息,但被随机数 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r 和系统参数 <math xmlns="http://www.w3.org/1998/Math/MathML"> α \alpha </math>α 彻底打乱了。
  • 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> B B </math>B (在 <math xmlns="http://www.w3.org/1998/Math/MathML"> G 2 G_2 </math>G2) : <math xmlns="http://www.w3.org/1998/Math/MathML"> B = [ β ] 2 + [ V J W T ( τ ) ] 2 + s [ δ ] 2 B = [\beta]2 + [V{JWT}(\tau)]_2 + s[\delta]_2 </math>B=[β]2+[VJWT(τ)]2+s[δ]2

    • 隐喻 : 电路验证逻辑的另一半,同样被随机数 <math xmlns="http://www.w3.org/1998/Math/MathML"> s s </math>s 混淆。
  • 计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C (在 <math xmlns="http://www.w3.org/1998/Math/MathML"> G 1 G_1 </math>G1 - 核心粘合剂) : <math xmlns="http://www.w3.org/1998/Math/MathML"> C = 1 δ ( Private p a r t ( β U + α V + W ) + H ( τ ) t ( τ ) ) + ( A s + B r − r s δ ) C = \frac{1}{\delta} \left( \text{Private}_{part}(\beta U + \alpha V + W) + H(\tau)t(\tau) \right) + (As + Br - rs\delta) </math>C=δ1(Privatepart(βU+αV+W)+H(τ)t(τ))+(As+Br−rsδ)

    • 隐喻 : <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C 包含了所有私有数据的校验和,以及商 <math xmlns="http://www.w3.org/1998/Math/MathML"> H H </math>H。它是为了让等式平衡而构造的"补丁"。

输出 : 用户发送 <math xmlns="http://www.w3.org/1998/Math/MathML"> π = ( A , B , C ) \pi = (A, B, C) </math>π=(A,B,C) 和公开的 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k e p h pk_{eph} </math>pkeph 到链上。


5.3 链上验证 (Verifier's Computation - On-Chain Contract)

智能合约(Verifier)不知道 JWT 长什么样,也不知道 Google 签名是多少。它只有 <math xmlns="http://www.w3.org/1998/Math/MathML"> v k vk </math>vk 和用户提交的 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k e p h pk_{eph} </math>pkeph。

1. 构建公开挑战 ( <math xmlns="http://www.w3.org/1998/Math/MathML"> L p u b L_{pub} </math>Lpub)

合约根据接收到的 <math xmlns="http://www.w3.org/1998/Math/MathML"> p k e p h pk_{eph} </math>pkeph 和写死在合约里的 Google 公钥指纹,计算公开输入的线性组合:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> [ L p u b ] 1 = 1 ⋅ [ IC 0 ] + Hash ( p k e p h ) ⋅ [ IC 1 ] + Hash ( P K G o o g l e ) ⋅ [ IC 2 ] [L_{pub}]_1 = 1 \cdot [\text{IC}0] + \text{Hash}(pk{eph}) \cdot [\text{IC}1] + \text{Hash}(PK{Google}) \cdot [\text{IC}_2] </math>[Lpub]1=1⋅[IC0]+Hash(pkeph)⋅[IC1]+Hash(PKGoogle)⋅[IC2]

(注: <math xmlns="http://www.w3.org/1998/Math/MathML"> IC i \text{IC}_i </math>ICi 是 <math xmlns="http://www.w3.org/1998/Math/MathML"> v k vk </math>vk 中预计算好的 <math xmlns="http://www.w3.org/1998/Math/MathML"> β u i + α v i + w i γ \frac{\beta u_i + \alpha v_i + w_i}{\gamma} </math>γβui+αvi+wi)

2. 最终配对检查 (The Pairing Check)

合约执行以下指令(消耗约 200k Gas):
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> e ( A , B ) = ? e ( α , β ) ⋅ e ( L p u b , γ ) ⋅ e ( C , δ ) e(A, B) \overset{?}{=} e(\alpha, \beta) \cdot e(L_{pub}, \gamma) \cdot e(C, \delta) </math>e(A,B)=?e(α,β)⋅e(Lpub,γ)⋅e(C,δ)

5.4 深度解析:为什么这个等式能确权?

让我们看看如果用户作弊会发生什么,以此反推验证的有效性。

情景一:用户拿了一个伪造的 JWT(签名不对)

  1. 在电路运算中,RSA 模幂约束无法满足。
  2. 导致 <math xmlns="http://www.w3.org/1998/Math/MathML"> U ⋅ V − W U \cdot V - W </math>U⋅V−W 产生了一个无法被 <math xmlns="http://www.w3.org/1998/Math/MathML"> t ( x ) t(x) </math>t(x) 整除的余数 <math xmlns="http://www.w3.org/1998/Math/MathML"> R ( x ) R(x) </math>R(x)。
  3. 用户在计算 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C 时,无法消除分母中的 <math xmlns="http://www.w3.org/1998/Math/MathML"> δ \delta </math>δ(因为余数项没法除尽)。
  4. 为了强行生成 <math xmlns="http://www.w3.org/1998/Math/MathML"> C C </math>C,用户只能瞎填一个点。
  5. 链上验算时: <math xmlns="http://www.w3.org/1998/Math/MathML"> e ( C , δ ) e(C, \delta) </math>e(C,δ) 产生的值将无法填补 <math xmlns="http://www.w3.org/1998/Math/MathML"> e ( A , B ) e(A, B) </math>e(A,B) 展开后的缺口。
  6. 结果:验证失败。

情景二:用户拿了别人的真实 JWT(偷来的),但想绑定自己的 Key

  1. JWT 签名是真的,RSA 约束通过。
  2. 但是 Nonce 绑定约束 失败:
    <math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> JWT.nonce ≠ Hash ( p k u s e r _ f a k e , salt ) \text{JWT.nonce} \neq \text{Hash}(pk_{user\_fake}, \text{salt}) </math>JWT.nonce=Hash(pkuser_fake,salt)
  3. 同样导致多项式无法整除。
  4. 结果:验证失败。

情景三:用户想根据 <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B A, B </math>A,B 反推 Google 签名

  1. <math xmlns="http://www.w3.org/1998/Math/MathML"> A = α + U + r δ A = \alpha + U + r\delta </math>A=α+U+rδ。
  2. 由于 <math xmlns="http://www.w3.org/1998/Math/MathML"> r r </math>r 是用户本地生成的随机数,对于链上观察者来说, <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 只是一个随机点。
  3. 根据离散对数难题 ,无法从点 <math xmlns="http://www.w3.org/1998/Math/MathML"> A A </math>A 还原出数值 <math xmlns="http://www.w3.org/1998/Math/MathML"> U U </math>U。
  4. 结果:隐私 100% 安全。

5.5 总结:Groth16 在 Keyless 中的数据流

步骤 数据状态 可见性 含义
Input JWT_String, Signature, Salt Private (用户本地) 原始凭证
Circuit RSA_Check, Nonce_Check Public (电路逻辑) 验证规则
Proof <math xmlns="http://www.w3.org/1998/Math/MathML"> A , B , C A, B, C </math>A,B,C (三个椭圆曲线点) Public (链上) "我知道凭证"的数学证据
Verify <math xmlns="http://www.w3.org/1998/Math/MathML"> e ( A , B ) = ... e(A,B) = \dots </math>e(A,B)=... Public (合约执行) 零知识放行

通过 Groth16,区块链合约得以在看不见 Google 签名的情况下,确信 Google 确实为该用户签发了证书。

相关推荐
有一个好名字2 小时前
力扣-链表最大孪生和
算法·leetcode·链表
无限进步_2 小时前
【C语言&数据结构】二叉树链式结构完全指南:从基础到进阶
c语言·开发语言·数据结构·c++·git·算法·visual studio
明月下2 小时前
【视觉算法——Yolo系列】Yolov11下载、训练&推理、量化&转化
算法·yolo
DYS_房东的猫2 小时前
《 C++ 零基础入门教程》第8章:多线程与并发编程 —— 让程序“同时做多件事”
开发语言·c++·算法
小郭团队2 小时前
1_1_七段式SVPWM (传统算法反正切)算法理论与 MATLAB 实现详解
人工智能·stm32·嵌入式硬件·算法·dsp开发
翟天保Steven3 小时前
医学影像-CBCT图像重建FDK算法
算法·医学影像·图像重建
星诺算法备案3 小时前
《算法安全自评估报告》的填报与实操(附模板)
人工智能·算法·备案·算法备案
AAD555888993 小时前
自动驾驶环境中的车辆目标检测——基于YOLO11-C3k2-RVB的改进算法
算法·目标检测·自动驾驶