密码学承诺方案:从哈希承诺到 Pedersen 承诺的数学原理

密码学概念 · 2026-07-28

摘要:密码学承诺方案是一种"加密后锁定"的原语,允许承诺方绑定一个值,同时在 reveal 阶段验证该值。本文详细分析哈希承诺和 Pedersen 承诺的数学构造与安全属性。

一、承诺方案定义

1.1 核心概念

承诺方案涉及两个参与者:

  • 承诺方(Committer):锁定一个值
  • 验证方(Verifier):后续验证该值

1.2 安全属性

属性定义安全含义
隐藏性(Hiding)承诺方无法从 Commit 值获知消息防止信息泄露
绑定性(Binding)承诺方无法改变已承诺的值防止篡改
一句话:隐藏性保护承诺值不被窥探,绑定性保护承诺值不被修改。


二、哈希承诺方案

2.1 构造方法

最简单直接的承诺方案:

CODE
Commit(m) = H(m || r)
Reveal(m, r) = (m, r)
Verify(m, r) = (Commit == H(m || r))

其中:

  • m:要承诺的消息
  • r:随机数(nonce)
  • H:密码学哈希函数(如 SM3、SHA-256)

2.2 安全性分析

隐藏性证明:

  • 由于 H 是单向函数,无法从 H(m||r) 反推 m
  • 随机数 r 增加了熵,使暴力破解不可行
绑定性证明:
  • 要改变承诺值,需要找到碰撞 H(m||r) = H(m'||r')
  • 对于安全哈希函数,计算碰撞的计算复杂度为 O(2^n/2)

2.3 局限性

问题说明解决方案
需要信任哈希函数如果 H 被攻破,方案失效使用已验证的哈希算法
无同态性无法对承诺值进行计算使用 Pedersen 承诺

三、Pedersen 承诺方案

3.1 构造方法

Pedersen 承诺由 Victor Shoup 于 1991 年提出,基于离散对数问题:

CODE
Commit(m, r) = g^m × h^r mod p

其中:

  • p:大素数
  • g, h:生成元,满足 log_g(h) 未知
  • m:消息(通常为整数)
  • r:随机数

3.2 参数生成

安全参数生成:

  • 选择安全素数 p, q(q | p-1)
  • 选择生成元 g = h^q mod p
  • 确保离散对数问题在阶为 q 的子群中困难
代码示例:

3.3 安全属性证明

隐藏性证明:

  • 给定 C = g^m × h^r mod p
  • 由于 log_g(h) 未知,对于任意 m',都存在 r' 使得 C = g^m' × h^r'
  • 因此无法从 C 推断 m
绑定性证明:
  • 要找到 (m, r) ≠ (m', r') 使得 g^m × h^r = g^m' × h^r' mod p
  • 等价于找到离散对数 log_g(h)
  • 假设离散对数问题困难,则绑定性成立

3.4 同态性质

Pedersen 承诺具有加法同态性:

CODE
Commit(m1, r1) × Commit(m2, r2) mod p
= g^(m1+m2) × h^(r1+r2) mod p
= Commit(m1+m2, r1+r2)

应用:

  • 电子投票:密文相加得到总票数
  • 私有集合求交:保护隐私的同时计算交集
  • 盲签名:签名者不知道签名内容

四、应用场景

4.1 电子投票

问题:如何确保投票隐私同时防止重复投票?

方案:

  • 每个选民对投票 c = Commit(vote, randomness)
  • 收集所有承诺值
  • 使用零知识证明验证投票有效性
  • 对承诺值进行同态加法得到总结果
  • 解密总结果

4.2 盲签名

流程:

CODE
1. Alice 选择随机数 r,计算 C = Commit(m, r)
2. Alice 将 C 发送给 Bob(签名者)
3. Bob 对 C 进行签名,返回 σ
4. Alice 从 σ 中提取对 m 的签名

安全保证:

  • Bob 不知道 m(隐藏性)
  • Alice 无法篡改 m(绑定性)

4.3 零知识证明

Pedersen 承诺是零知识证明的基础构件:

场景:证明我知道 x 使得 H = g^x,但不知道 x 具体值。

协议:

CODE
1. Prover 选择随机 k,计算 T = g^k
2. Verifier 发送随机挑战 e
3. Prover 计算响应 s = k + e·x
4. Verifier 验证 g^s = T × H^e


五、实现注意事项

5.1 随机数选择

要求:

  • 随机数必须足够长(建议 ≥ 256 位)
  • 必须使用密码学安全随机数生成器
错误示例:
PYTHON
# ❌ 错误:使用伪随机数
r = random.randint(0, p)

# ✅ 正确:使用 CSPRNG
r = os.urandom(32)

5.2 参数验证

验证清单:

  • [ ] p 是安全素数
  • [ ] q = (p-1)/2 也是素数
  • [ ] g, h 的阶为 q
  • [ ] log_g(h) 无法计算

5.3 性能优化

优化方法说明效果
预计算预计算 g^m 表加速多次承诺
批处理批量验证承诺减少计算次数
GPU 加速并行计算指数提升吞吐量

六、与国密的结合

6.1 SM3 哈希承诺

使用 SM3 作为哈希函数:

PYTHON
from gmssl import sm3, func

def commit_with_sm3(m: bytes, r: bytes) -> str:
    """使用 SM3 的承诺方案"""
    data = m + r
    return sm3.sm3_hash(func.bytes_to_list(data))

6.2 SM2 椭圆曲线承诺

基于 SM2 曲线的 Pedersen 承诺:

  • 使用 sm2p256v1 曲线
  • 消息和随机数在曲线阶 q 上
  • 承诺值为曲线上的点
注意:SM2 曲线参数与标准 Pedersen 不同,需要调整。


七、总结

密码学承诺方案是密码学的基础构件:

方案隐藏性绑定性同态性适用场景
哈希承诺✅✅❌简单场景
Pedersen✅✅✅复杂协议
实施建议:
  • 简单场景使用哈希承诺
  • 需要同态性的场景使用 Pedersen 承诺
  • 随机数长度 ≥ 256 位
  • 国密场景优先使用 SM2/SM3

参考

  • Shoup, V. (1991). "Efficient Implementation of Legalizable Renunciation"
  • Bellare, M., & Rogaway, P. (1993). "Commitment Schemes with User Error"
  • GM/T 0003-2012《SM2 椭圆曲线公钥密码算法》
  • GM/T 0004-2012《SM3 密码杂凑算法》