密码学系列 - 零知识证明(ZKP) - Schnorr协议

(一)交互式

Schnorr 零知识证明协议 (ZKP Schnorr Protocol) 是基于 Schnorr 签名方案的一种交互式零知识证明协议,用于证明某人拥有某个秘密密钥,而不透露该密钥本身。它是一种 Sigma 协议,由三步组成:承诺、挑战和响应。以下是详细的描述:

Schnorr ZKP 协议概述

公共参数
  • 椭圆曲线参数 : 一个素数 p p p,定义有限域 F p \mathbb{F}_p Fp。
  • 生成元 : 一个生成元 G G G。
  • 公钥 : P = x G P = xG P=xG,其中 x x x是私钥。
证明目标

证明者 (Prover) 需要向验证者 (Verifier) 证明自己知道私钥 x x x,但不透露 x x x的实际值。

协议步骤(交互式)

  1. 承诺阶段(Commitment Phase):

    • 证明者选择一个随机数 r r r并计算承诺 R = r G R = rG R=rG。
    • 证明者将 R R R发送给验证者。
  2. 挑战阶段(Challenge Phase):

    • 验证者选择一个随机挑战 c c c并发送给证明者。
  3. 响应阶段(Response Phase):

    • 证明者计算响应 s = r + c x m o d    p s = r + cx \mod p s=r+cxmodp。
    • 证明者将 s s s发送给验证者。
  4. 验证阶段(Verification Phase):

    • 验证者计算 s G sG sG和 R + c P R + cP R+cP。
    • 如果 s G = R + c P sG = R + cP sG=R+cP,则验证通过,否则验证失败。

数学解释

通过以下等式,验证者可以确认 s s s是由 r r r和 x x x计算得来的:

s G = ( r + c x ) G = r G + c x G = R + c P sG = (r + cx)G = rG + cxG = R + cP sG=(r+cx)G=rG+cxG=R+cP

示例代码

下面是一个使用 Python 和 ecdsa 库实现的 Schnorr ZKP 协议示例。

安装依赖

首先,安装 ecdsa 库:

sh 复制代码
pip install ecdsa
实现代码
python 复制代码
import os
from ecdsa import SigningKey, SECP256k1
from hashlib import sha256

# 公共参数
curve = SECP256k1
G = curve.generator
order = curve.order

# 证明者 (Prover) 的私钥和公钥
private_key = SigningKey.generate(curve=curve)
public_key = private_key.get_verifying_key()
x = private_key.privkey.secret_multiplier
P = public_key.pubkey.point

# 承诺阶段
r = int.from_bytes(os.urandom(32), byteorder='big') % order
R = r * G

# 验证者选择挑战
c = int.from_bytes(os.urandom(32), byteorder='big') % order

# 证明者计算响应
s = (r + c * x) % order

# 验证者验证
lhs = s * G
rhs = R + c * P

print("sG: ", lhs)
print("R + cP: ", rhs)

if lhs == rhs:
    print("验证通过:证明者知道私钥 x")
else:
    print("验证失败")

零知识性质

Schnorr ZKP 协议具有零知识性质,满足以下三个要求:

  1. 完备性(Completeness) :
    • 如果证明者诚实地执行协议,验证者一定会接受证明。
  2. 可靠性(Soundness) :
    • 如果证明者不知道秘密密钥 x x x,则验证者能够检测到欺骗行为。
  3. 零知识性(Zero-Knowledge) :
    • 验证者在协议过程中无法获得关于秘密密钥 x x x的任何信息,除了它是有效的。

为了进一步确保协议的安全性和零知识性,实际应用中通常会增加随机数的位数和使用更复杂的密码学哈希函数。

总结

Schnorr 零知识证明协议是一种简单且高效的协议,能够在不泄露秘密信息的情况下,证明某人拥有该信息。它的主要应用包括密码学、区块链和身份验证等领域。通过以上步骤和示例代码,展示了如何实现并验证 Schnorr ZKP 协议。

(二)非交互式(通过Fiat-Shamir变换)

Fiat-Shamir变换是一种将交互式零知识证明协议(如Schnorr协议)转换为非交互式零知识证明协议的方法。这种转换使得证明者可以生成一个证明,该证明可以由任何验证者离线验证,而无需交互。Fiat-Shamir变换通过将挑战阶段中的随机选择替换为基于哈希函数的确定性选择来实现。

Fiat-Shamir 变换概述

非交互式零知识证明协议(通过Fiat-Shamir变换)

Fiat-Shamir变换消除了交互需求,生成一个可公开验证的证明。

实现Fiat-Shamir变换

以下是将Schnorr协议通过Fiat-Shamir变换转换为非交互式零知识证明协议的步骤和示例代码:

公共参数
  • 椭圆曲线参数:有限域 ( \mathbb{F}_p ) 的素数 ( p ) 和生成元 ( G )。
  • 公钥:( P = xG ),其中 ( x ) 是私钥。
证明者步骤
  1. 承诺阶段
    • 证明者选择一个随机数 ( r ),计算承诺 ( R = rG )。
  2. 生成挑战
    • 证明者计算挑战 ( c ) 作为哈希值:( c = H(m || R) ),其中 ( m ) 是消息,( H ) 是哈希函数。
  3. 响应阶段
    • 证明者计算响应 ( s = r + cx \mod n )。
  4. 生成证明
    • 证明者将 ((R, s)) 作为证明。
验证者步骤
  1. 验证证明
    • 验证者计算挑战 ( c = H(m || R) )。
    • 验证 ( sG = R + cP )。

示例代码

以下是一个使用Python和 ecdsa 库实现Fiat-Shamir变换的示例代码。

安装依赖
sh 复制代码
pip install ecdsa
实现代码
python 复制代码
import os
from ecdsa import SigningKey, SECP256k1
from hashlib import sha256

# 公共参数
curve = SECP256k1
G = curve.generator
order = curve.order

# 哈希函数
def hash_function(*args):
    m = sha256()
    for arg in args:
        if isinstance(arg, int):
            m.update(arg.to_bytes((arg.bit_length() + 7) // 8, byteorder='big'))
        elif isinstance(arg, bytes):
            m.update(arg)
        else:
            raise TypeError("Unsupported type for hashing")
    return int.from_bytes(m.digest(), byteorder='big') % order

# 证明者 (Prover) 的私钥和公钥
private_key = SigningKey.generate(curve=curve)
public_key = private_key.get_verifying_key()
x = private_key.privkey.secret_multiplier
P = public_key.pubkey.point

# 证明者生成证明
message = b"Hello, this is a message."
r = int.from_bytes(os.urandom(32), byteorder='big') % order
R = r * G

c = hash_function(message, R)
s = (r + c * x) % order

# 证明 (R, s)
proof = (R, s)

# 验证者验证证明
def verify_proof(message, R, s, P):
    c = hash_function(message, R)
    lhs = s * G
    rhs = R + c * P
    return lhs == rhs

# 验证证明
if verify_proof(message, *proof, P):
    print("验证通过:证明者知道私钥 x")
else:
    print("验证失败")

关键点

  • 哈希函数:哈希函数 ( H ) 的选择非常关键,通常使用SHA-256等加密哈希函数。
  • 零知识性质:通过Fiat-Shamir变换,证明保持了零知识性质,因为哈希函数的不可预测性模拟了随机挑战的效果。
  • 安全性:非交互式零知识证明在离线环境中非常有用,因为证明者可以预先生成证明,任何人都可以在任何时间进行验证。

总结

Fiat-Shamir变换是将交互式零知识证明协议转换为非交互式协议的强大工具,使得证明过程更为简便,特别适用于区块链和分布式系统中的应用。通过上述步骤和示例代码,展示了如何实现和验证基于Fiat-Shamir变换的Schnorr协议。


: 区块链知识系列
: 密码学系列
: 零知识证明系列
: 共识系列
: 公链调研系列
: BTC系列
: 以太坊系列
: EOS系列
: Filecoin系列
: 联盟链系列
: Fabric系列
: 智能合约系列
: Token系列

相关推荐
2501_948120155 小时前
基于RFID技术的固定资产管理软件系统的设计与开发
人工智能·区块链
老蒋每日coding7 小时前
Web3 开发入门:用 Ethers.js 玩转以太坊交易与合约
web3·区块链
AC赳赳老秦8 小时前
专利附图说明:DeepSeek生成的专业技术描述与权利要求书细化
大数据·人工智能·kafka·区块链·数据库开发·数据库架构·deepseek
暴躁小师兄数据学院18 小时前
【WEB3.0零基础转行笔记】基础知识篇—第一讲:区块链基础
笔记·web3·区块链
中金快讯18 小时前
FP Markets澳福点差竞争力存疑?澳福低成本策略能否重塑优势?
人工智能·区块链
泷fyk18 小时前
区块链+AI数据管理产品设计方案
大数据·人工智能·区块链
皮皮学姐分享-ppx19 小时前
中国城市间交通驾车距离矩阵(2024)
大数据·人工智能·经验分享·科技·区块链
草原猫2 天前
产业数智化:DAPP开发赋能实体行业的实践与探索
区块链·dapp开发
China_Yanhy2 天前
我的区块链运维日记 · 第 13 日:跨链惊魂 —— Layer 2 的“快”与“慢”
运维·区块链