🤫 零知识证明

证明"我知道"而不泄露"我知道什么"——密码学最优雅的发明。
从 zk-SNARK 到 zk-STARK,从隐私交易到 AI 推理可验证性。

🧠 零知识证明:密码学最优雅的发明

1985 年,Goldwasser、Micali 和 Rackoff 在论文中定义了零知识证明 (Zero-Knowledge Proof, ZKP):一个证明者 (Prover) 可以向验证者 (Verifier) 证明某个声明为真,而不泄露任何超出声明本身的信息

三个核心性质

🔒 完备性 (Completeness)

如果声明为真,诚实的证明者总是能说服诚实的验证者。即"真的假不了"——正确声明的证明一定能通过验证。

🛡️ 可靠性 (Soundness)

如果声明为假,作弊的证明者几乎不可能说服诚实的验证者。即"假的真不了"——错误声明的证明极大概率被拒绝(允许极小概率的误差,如 2-128)。

🤫 零知识性 (Zero-Knowledge)

验证者在验证完成后,除了"声明为真"这一事实外,不获得任何额外信息。形式化:存在一个模拟器 (Simulator) 不需要知道秘密就能生成与真实证明不可区分的"假"证明。

经典直觉例子:阿里巴巴洞穴

最著名的 ZKP 直觉解释是 Jean-Jacques Quisquater 等人的"阿里巴巴洞穴"故事:

这是一个交互式零知识证明。现代 ZKP 系统(SNARK/STARK)是非交互式的——证明者生成一个证明,验证者可以离线验证。

ZKP 的关键分类维度

维度类型 A类型 B说明
交互性交互式 (Interactive)非交互式 (Non-interactive)NIZK 通过 Fiat-Shamir 变换或 CRS 实现
证明大小简洁 (Succinct)非简洁简洁证明通常 < 1KB,验证时间 < 10ms
透明性需要可信设置 (Trusted Setup)透明 (Transparent)可信设置是安全隐患——有毒废物 (Toxic Waste)
后量子安全非后量子后量子安全基于椭圆曲线的不抗量子,基于哈希的抗量子

⚡ zk-SNARK vs zk-STARK:两大主流方案

zk-SNARK:简洁非交互知识论证

zk-SNARK (Zero-Knowledge Succinct Non-interactive Argument of Knowledge) 是目前最广泛使用的 ZKP 方案。Zcash 最初使用它实现隐私交易。

特性zk-SNARKzk-STARK
全称Succinct Non-interactive ARgument of KnowledgeScalable Transparent ARgument of Knowledge
密码学假设椭圆曲线配对 (Pairing),如 BN254/BLS12-381抗碰撞哈希函数,如 SHA-256/Keccak
可信设置⚠️ 需要 (Ceremony/CRS)✅ 不需要 (Transparent)
证明大小极小 (~288 字节)较大 (~50-200 KB)
验证时间极快 (~1-10 ms)快 (~10-100 ms)
证明时间中等 (秒级)较慢 (秒~分钟级)
后量子安全❌ 不安全(依赖椭圆曲线)✅ 安全(仅依赖哈希)
代表实现Groth16, PLONK, MarlinSTARK, Fractal, Winterfell
代表应用Zcash, Filecoin, Tornado CashEthereum EIP-4844, StarkNet, zkSync
标准化ZKProof 社区推进ZKProof 社区推进
为什么可信设置 (Trusted Setup) 是问题?zk-SNARK 需要一个"公共参考串" (CRS) 的生成过程,这个过程中产生的随机性("有毒废物")如果未被销毁,持有者可以伪造证明。虽然多人参与 Ceremony 可以降低风险(一人诚实即可保证安全),但这是额外的信任假设。zk-STARK 不需要可信设置,这是它的核心优势。

SNARK 变体对比

方案设置类型证明大小特点
Groth16每个电路单独设置~192 字节(最小)证明最小最快,但每个电路需新设置。Zcash 使用
PLONK通用设置(一次)~400 字节通用 CRS,不同电路可复用。灵活性高
Marlin通用设置~1 KBPLONK 的改进版,更好的组合性
Halo 2无需设置(递归)可变Zcash 团队开发,支持递归证明,无需可信设置
SP1 (Succinct)无需设置可变Rust 生态,支持 RISC-V 程序证明,开发体验好

递归证明:ZKP 的"组合"超能力

递归证明 (Recursive Proof) 是 ZKP 最强大的特性之一——一个 ZKP 可以验证另一个 ZKP。这意味着:

ZKP 在区块链之外的真正价值:大多数人对 ZKP 的印象停留在"隐私币"和"Layer 2 扩容"。但 ZKP 的本质是可验证计算——它让一方可以高效地验证另一方确实执行了某个计算。这是 AI 推理可验证性、去中心化计算市场、外包计算验证的基础设施。

🤖 零知识证明的 AI 应用

🧠 推理可验证性

问题:AI 服务声称用了 GPT-4 跑推理,但用户无法验证是否偷偷用了更便宜的模型。

ZKP 方案:服务商用 ZKP 证明"我确实按照模型 M 执行了推理,输入是 x,输出是 y"——而不泄露模型权重。

状态:研究阶段,已有原型系统(EZKL、zkML)

🪪 隐私身份验证

问题:验证"我是成年人"需要出示身份证,泄露姓名、出生日期、地址等全部信息。

ZKP 方案:用 ZKP 证明"我的出生日期在 2000 年之前"——仅此一条信息,不泄露其他任何信息。

状态:已有商业部署(Polygon ID、zkPass)

📊 隐私数据分析

问题:银行想证明其风控模型在特定人群上的公平性,但不能公开客户数据。

ZKP 方案:用 ZKP 证明"在加密数据集上,模型的公平性指标满足阈值"——不泄露任何客户数据。

状态:研究阶段

🔐 数据合规证明

问题:GDPR 要求数据处理合规,但审计者直接查看数据又违反隐私。

ZKP 方案:用 ZKP 证明"数据处理流程符合 GDPR 规则"——审计者验证证明而不需要看数据。

状态:概念验证阶段

🎨 模型水印验证

问题:如何证明某个 AI 模型是你的知识产权?

ZKP 方案:在模型中嵌入水印,用 ZKP 证明"这个模型包含我的水印"——不泄露水印的具体位置和内容。

状态:研究阶段

💰 去中心化 AI 市场

问题:去中心化市场中,如何验证算力提供者确实执行了计算?

ZKP 方案:算力提供者提交计算结果 + ZKP,市场合约自动验证证明后释放付款。

状态:早期实践(Gensyn、Ritual)

现实应用案例

项目/产品ZKP 类型用途成熟度
ZcashGroth16 → Halo 2隐私交易:隐藏发送者、接收者、金额生产级
Tornado Cashzk-SNARKEthereum 交易混币器(被制裁但技术有效)生产级
StarkNetzk-STARKEthereum L2 扩容:证明批量交易有效性生产级
zkSync Erazk-SNARK (Boojum)Ethereum L2 扩容,SNARK 证明 EVM 执行生产级
Polygon Midenzk-STARK隐私 L2,支持私有状态和公开状态测试网
Polygon IDzk-SNARK (Circom)去中心化身份,选择性披露可用
Worldcoinzk-SNARK (Semaphore)人格证明:证明是真人不泄露生物信息生产级
EZKLzk-SNARK (Halo 2)ML 模型推理的零知识证明研究/原型
zkPasszk-TLS用 ZKP 证明 HTTPS 网站数据而不泄露凭证可用

🧮 zkML:零知识机器学习

zkML (Zero-Knowledge Machine Learning) 是 ZKP 与 ML 的交叉领域——用零知识证明来验证机器学习推理过程。这是 AI 时代 ZKP 最有前途的应用方向之一。

zkML 的三种模式

模式 1:模型完整性

证明:"我确实用模型 M 对输入 x 做了推理,输出 y"

保护:模型权重可以是私有的

用途:API 服务商向客户证明没有偷换模型

模式 2:输入隐私

证明:"在私有输入 x 上,公开模型 M 的推理结果是 y"

保护:用户输入数据不泄露给验证者

用途:医疗诊断、金融风控等隐私敏感场景

模式 3:双向隐私

证明:"在私有输入 x 上,私有模型 M 的推理结果是 y"

保护:输入和模型都不泄露

用途:模型 IP 保护 + 用户隐私的双重要求

zkML 技术栈

层级工具/框架说明
模型导出ONNX → ZKP 电路将 ML 模型导出为 ONNX 格式,再转译为 ZKP 电路
ZKP 后端Halo 2, PLONK, Groth16实际的证明系统
ML-ZKP 框架EZKL, keras2circom, zkCNN将 ML 操作映射到 ZKP 算术电路
优化层量化、算子融合、查找表将浮点运算量化为整数,减少电路约束数量
部署链上验证 / API 服务在区块链或 API 中验证证明

zkML 当前性能(截至 2025)

模型参数量证明时间验证时间证明大小
MNIST MLP~1K~1 秒~10 ms~10 KB
小型 CNN~10K~10 秒~50 ms~50 KB
ResNet-18~11M~分钟级~秒级~数 MB
GPT-2 Small~124M小时级分钟级~数 GB
Llama 7B~7B不现实不现实不现实
zkML 的现实:当前 zkML 能处理小型模型(MNIST、简单 CNN),但大模型的证明开销仍然太高。然而,技术进步速度惊人——2022 年证明 MNIST 需要分钟级,2024 年已降至秒级。预计 3-5 年内小型 Transformer 也能实现实用化。不需要证明整个模型——只需要证明关键层或关键决策步骤。

zkML 的替代方案:不一定要证明整个模型

💻 代码示例

Circom:编写 ZKP 电路

Circom 是最流行的 ZKP 电路语言,配合 snarkjs 使用:

// range_check.circom — 证明一个值在 [0, max) 范围内
// 实际应用:证明年龄 ≥ 18 而不泄露具体年龄

pragma circom 2.1.5;

template RangeCheck(n) {
    // 证明 input 在 [0, 2^n) 范围内
    signal input in;
    signal output out;

    // 使用位分解证明值在范围内
    component bits[n];
    for (var i = 0; i < n; i++) {
        bits[i] = Num2Bits(1);
    }

    // 约束:重构的值必须等于输入
    // 这是零知识证明的核心——通过约束保证计算的正确性
}

// 更实用的例子:证明 age >= 18 而不泄露具体年龄
template AgeVerification() {
    signal input age;        // 私有输入:实际年龄
    signal input difference; // 私有输入:age - 18
    signal output isValid;   // 公开输出:是否 ≥ 18

    // 约束:age - 18 = difference
    // 如果 age < 18,difference 会溢出,约束失败
    component isPositive = GreaterEqThan(8); // 8位足够表示年龄差
    isPositive.in[0] <== age;
    isPositive.in[1] <== 18;
    isValid <== isPositive.out;
}

component main {public [isValid]} = AgeVerification();

snarkjs:生成和验证证明

# 1. 编译电路
circom age_verification.circom --r1cs --wasm --sym

# 2. 可信设置 (Powers of Tau Ceremony)
snarkjs powersoftau new bn128 12 pot12_0000.ptau -v
snarkjs powersoftau contribute pot12_0000.ptau pot12_0001.ptau \
  --name="First contribution" -v

# 3. 电路特定设置 (Phase 2)
snarkjs setup --r1cs age_verification.r1cs \
  --pk verification_key.json \
  --vk proving_key.json

# 4. 生成证明
# input.json: {"age": 25, "difference": 7}
snarkjs calculatewitness age_verification.wasm input.json
snarkjs proof proving_key.json witness.wtns proof.json public.json

# 5. 验证证明 — 验证者只需要 verification_key + proof + public 输出
# 验证者不知道 age = 25,只知道 isValid = 1
snarkjs verify verification_key.json public.json proof.json
# 输出: [INFO] snarkJS: OK!

# ⚡ 关键:验证者只知道"这个人 ≥ 18 岁",不知道具体年龄!

Python:模拟零知识证明的交互式协议

import random
import hashlib

"""
简化版交互式 ZKP:证明知道离散对数
场景:Peggy 知道 x 使得 g^x = y (mod p)
她想证明知道 x 而不泄露 x
"""

# 参数(实际中 p 是大素数,如 2048 位)
p = 2**127 - 1  # 梅森素数(仅演示,实际用安全素数)
g = 2           # 生成元
x = 42          # Peggy 的秘密
y = pow(g, x, p)  # 公开值:g^x mod p

def peggy_commit():
    """Peggy 生成承诺:随机选 r,发送 g^r"""
    r = random.randint(2, p - 1)
    commitment = pow(g, r, p)
    return r, commitment

def victor_challenge():
    """Victor 发送随机挑战 c"""
    return random.randint(0, 1)

def peggy_respond(r, c, x):
    """Peggy 根据挑战计算响应"""
    if c == 0:
        return r          # 响应 = r
    else:
        return (r + x) % (p - 1)  # 响应 = r + x

def victor_verify(commitment, c, s, y, g, p):
    """Victor 验证响应"""
    if c == 0:
        return pow(g, s, p) == commitment
    else:
        return pow(g, s, p) == (commitment * y) % p

# 运行交互式协议 n 轮
n_rounds = 20
all_passed = True
for i in range(n_rounds):
    r, commitment = peggy_commit()
    c = victor_challenge()
    s = peggy_respond(r, c, x)
    if not victor_verify(commitment, c, s, y, g, p):
        all_passed = False
        break

if all_passed:
    print(f"✅ {n_rounds} 轮全部通过 — 以 1-2^(-{n_rounds}) 概率确认 Peggy 知道 x")
    print(f"   Victor 仍然不知道 x 的值是多少!")
else:
    print("❌ 验证失败")

EZKL:ML 模型的零知识证明

# 安装 EZKL
# pip install ezkl

import ezkl
import json
import torch
import torch.nn as nn

# 定义简单模型(MNIST 分类器)
class SimpleModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 10)

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        return self.fc2(x)

model = SimpleModel()
model.eval()

# 导出 ONNX
dummy_input = torch.randn(1, 784)
torch.onnx.export(model, dummy_input, "model.onnx")

# 生成 EZKL 设置
ezkl.gen_settings("model.onnx", "settings.json")

# 生成电路
ezkl.calibrate_settings(
    "settings.json",
    "model.onnx",
    "input.json",  # 包含测试输入数据
    "resources"     # 资源限制
)

# 编译电路 → 生成证明 → 验证
ezkl.compile_circuit("model.onnx", "model.ezkl", "settings.json")
ezkl.setup("model.ezkl", "settings.json", "vk.key", "pk.key")
ezkl.prove("model.ezkl", "input.json", "witness.json",
           "pk.key", "proof.json", "settings.json")
result = ezkl.verify("proof.json", "settings.json", "vk.key")
print(f"✅ ZKP 验证结果: {result}")

⚠️ 零知识证明的挑战与局限

🐌 性能瓶颈

证明生成仍然是性能瓶颈。对于复杂计算(如 ML 推理),证明时间可能比直接计算慢 1000-10000 倍。硬件加速(GPU/FPGA/ASIC)正在改善。

🔧 开发门槛

编写 ZKP 电路需要密码学专业知识。Circom/Noir/etc 降低了门槛但仍不简单。AI 工程师很难直接上手。

⚠️ 可信设置风险

SNARK 的可信设置是安全隐患。虽然多人 Ceremony 降低了风险,但"有毒废物"的存在仍让保守的安全团队担忧。

🔄 电路升级困难

ZKP 电路是编译时确定的。模型更新后需要重新编译电路和生成新密钥,这增加了运维复杂度。

📐 精度问题

ZKP 电路在有限域上运算,而 ML 模型使用浮点数。量化误差是 zkML 的核心难题——精度损失可能影响模型准确率。

🧪 审计不足

ZKP 电路的安全性审计远不如传统软件成熟。一个错误的约束可能导致安全漏洞——证明者可以伪造证明。

💡 实用建议:不要为了用 ZKP 而用 ZKP。如果你的场景可以用更简单的技术(TEE、MPC、数字签名)解决,先用简单方案。ZKP 的价值在于无可信第三方的可验证计算——当你确实需要这个属性时才值得付出性能代价。

📖 学习资源

📚 入门

  • ZKProof Standardszkproof.org 标准化参考
  • 零知识证明:从入门到精通 — 安比实验室中文教程
  • Proofs, Arguments, and Zero-Knowledge — Justin Thaler 著,理论教材
  • zkintro.com — 交互式 ZKP 学习

🛠️ 实操

  • Circom + snarkjs — 最成熟的 ZKP 开发工具链
  • Noir — Aztec 团队的 ZKP 语言,更现代
  • EZKL — ML 模型 ZKP 证明
  • SP1 — Succinct 的 RISC-V ZKP 虚拟机

🔬 前沿

  • Cryptology ePrint Archive — 最新论文
  • ZK Hack — ZKP 黑客松和挑战
  • Protocol Labs Research — Filecoin/ZKP 研究
  • Ethereum Research Forum — ZKP 应用于 L2