密码学承诺方案:从哈希承诺到 Pedersen 承诺的数学原理与安全分析
概述
密码学承诺方案(Cryptographic Commitment Scheme)是现代密码学中最基础、最优雅的构造之一。它的核心思想直观而深刻:
承诺者(Committer)可以"密封"一个值并交给验证者(Verifier),之后打开时只能揭示原始值——既不能反悔更改(Binding),又不能让验证者提前获知(Hiding)。这一思想由 Manuel Blum 于 1982 年正式提出(虽然更早的雏形可追溯到 1970 年代的 coin-flipping 协议)。如今,承诺方案已成为构建更复杂密码协议的"乐高积木"——零知识证明、安全多方计算、数字拍卖、区块链(Merkle 树即哈希承诺的链式结构)、电子投票等系统都离不开它。
承诺方案的一个经典类比:
- 承诺阶段:Alice 选择一个秘密数字,把写有该数字的信封密封后交给 Bob
- 打开阶段:Alice 打开信封,Bob 验证其中的数字与之前一致
形式化定义
一个承诺方案由两个算法和一个协议组成:
$$\mathsf{Commit}(m; r) \rightarrow c$$
$$\mathsf{Open}(c, m, r) \rightarrow \{0, 1\}$$
其中 $m$ 为要承诺的消息,$r$ 为随机数(称为"打开密钥"或"盲化因子"),$c$ 为承诺值。
三大核心安全属性
| 属性 | 定义 | 含义 |
|---|---|---|
| 计算绑定性(Computational Binding) | 对于任意多项式时间敌手 $\mathcal{A}$,找到 $m' \neq m$ 使得 $\mathsf{Open}(c, m', r') = 1$ 的概率可忽略 | 承诺后无法篡改消息 |
| 信息论隐藏性(Information-Theoretic Hiding) | 对于任意计算能力的验证者,不同消息对应的承诺值在统计上不可区分 | 承诺阶段无法获知消息 |
| 完美绑定性(Perfect Binding) | 不存在任何 $m' \neq m, r'$ 使得 $\mathsf{Commit}(m; r) = \mathsf{Commit}(m'; r')$ | 数学上不可能篡改 |
哈希承诺(Hash-Based Commitment)
构造原理
哈希承诺是最简单、最实用的承诺方案,基于密码学哈希函数的抗碰撞性和单向性:
$$\mathsf{Commit}(m; r) = H(r \| m)$$
$$\mathsf{Open}(c, m, r): \text{验证 } c \stackrel{?}{=} H(r \| m)$$
其中 $H$ 为密码学哈希函数,$r$ 为足够长的随机数(建议 $\geq 256$ bit)。
安全分析
| 属性 | 保证 | 依赖假设 |
|---|---|---|
| 绑定性 | 计算绑定 | 哈希函数的抗碰撞性 |
| 隐藏性 | 计算隐藏(若 $r$ 足够长) | 哈希函数的伪随机性 |
基于 SM3 的构造
GM/T 0004-2012 定义的 SM3 密码杂凑算法输出 256 bit,适用于构建安全的哈希承诺:
$$\mathsf{Commit}_{\text{SM3}}(m; r) = \text{SM3}(r \| m)$$
其中 $r \in_R \{0, 1\}^{256}$。SM3 的安全性相当于 SHA-256,满足碰撞抵抗和原像抵抗要求。
Python 实现(基于 GM/T 0004-2012 SM3)
import os
import hashlib
def sm3_hash(data: bytes) -> bytes:
"""基于 GM/T 0004-2012 的 SM3 哈希(使用 cryptography 库)"""
from cryptography.hazmat.primitives.hashes import Hash, SM3
h = Hash(SM3())
h.update(data)
return h.finalize()
def commit(m: bytes, r: bytes = None) -> tuple:
"""
哈希承诺:Commit(m; r) = H(r || m)
参数:
m: 要承诺的消息(bytes)
r: 随机数(可选,默认生成 32 字节)
返回:
(commitment, r): 承诺值和打开密钥
"""
if r is None:
r = os.urandom(32) # 256-bit 随机数
c = sm3_hash(r + m)
return c, r
def open_check(c: bytes, m: bytes, r: bytes) -> bool:
"""
打开承诺:验证 c == H(r || m)
"""
c_prime = sm3_hash(r + m)
return c_prime == c
# 示例
message = b"secret_bid_9999"
c, r = commit(message)
print(f"承诺值: {c.hex()}")
print(f"打开结果: {open_check(c, message, r)}") # True
print(f"篡改结果: {open_check(c, b'fake_bid', r)}") # False应用场景
哈希承诺在工程实践中极为广泛:
- 区块链 Merkle 树:每个叶子节点是交易的哈希承诺,根承诺代表整棵树的完整性
- 数字拍卖:投标者先提交承诺(密封报价),开标阶段打开承诺
- 零知识证明:证明者先对见证(witness)做承诺,后续基于承诺构造响应
- 密码学投票:选民先提交选票承诺,防止投票后修改
Pedersen 承诺(Pedersen Commitment)
构造原理
Pedersen 承诺由 Torben Pedersen 于 1991 年提出,基于离散对数问题的困难性。它是一种完美隐藏、计算绑定的承诺方案。
设 $G$ 为素数阶 $q$ 的循环群,$g$ 为生成元,$h = g^\alpha$($\alpha$ 未知)。承诺:
$$\mathsf{Commit}_{\text{Pedersen}}(m; r) = g^m \cdot h^r$$
其中 $m \in \mathbb{Z}_q$ 为消息,$r \in_R \mathbb{Z}_q$ 为盲化因子。
安全分析
| 属性 | 保证 | 依赖假设 |
|---|---|---|
| 隐藏性 | 完美隐藏(Perfect Hiding) | $h^r$ 在群上均匀分布 |
| 绑定性 | 计算绑定(Computational Binding) | 离散对数假设(DLP) |
绑定性证明:若敌手能找到 $(m', r') \neq (m, r)$ 使得 $g^m h^r = g^{m'} h^{r'}$,则 $g^{m-m'} = h^{r'-r} = \alpha^{\alpha(r'-r)}$,可计算 $\alpha$ 的离散对数,违反 DLP 假设。
基于 SM2 曲线的构造
SM2 椭圆曲线(GB/T 32918.5-2016)定义了 256-bit 素数域上的曲线,满足 Pedersen 承诺所需的群结构:
$$E: y^2 = x^3 + ax + b \quad \text{over } \mathbb{F}_p$$
取生成元 $G$,随机点 $H = [\alpha]G$($\alpha$ 未知),承诺:
$$\mathsf{Commit}_{\text{SM2}}(m; r) = [m]G + [r]H$$
其中 $m, r \in \mathbb{Z}_n$($n$ 为 $G$ 的阶)。
代码示例(数学原理演示)
# Pedersen 承诺的数学原理演示(使用小参数便于理解)
def pedersen_commit(m: int, r: int, p: int, g: int, h: int) -> int:
"""
Pedersen 承诺:c = g^m * h^r mod p
参数:
m: 消息(整数)
r: 盲化因子
p: 素数模数
g: 生成元
h: 第二生成元(h = g^alpha,alpha 未知)
"""
return (pow(g, m, p) * pow(h, r, p)) % p
def pedersen_open(c: int, m: int, r: int, p: int, g: int, h: int) -> bool:
"""验证承诺"""
c_prime = (pow(g, m, p) * pow(h, r, p)) % p
return c == c_prime
# 示例(使用小参数演示)
p = 7919 # 小素数,仅作演示
g = 7 # 生成元
alpha = 12345 # 秘密值(实际部署中应丢弃)
h = pow(g, alpha, p)
m = 42 # 要承诺的消息
r = 5678 # 随机盲化因子
c = pedersen_commit(m, r, p, g, h)
print(f"承诺值: {c}")
print(f"打开验证: {pedersen_open(c, m, r, p, g, h)}") # True
print(f"篡改验证: {pedersen_open(c, 99, r, p, g, h)}") # False⚠️ 工程提示:上述代码使用小参数演示数学原理。实际部署应使用 GM/T 0003.5-2012 定义的 SM2 曲线参数(256-bit),配合 gmssl 或 cryptography 库的椭圆曲线点运算。
ElGamal 承诺(ElGamal Commitment)
构造原理
ElGamal 承诺基于 ElGamal 加密算法的变体,是一种完美绑定、计算隐藏的方案:
$$\mathsf{Commit}_{\text{ElGamal}}(m; r) = (g^r, h^r \cdot g^m)$$
其中 $(g, h)$ 为公钥参数,$r$ 为随机数,$g^m$ 表示消息 $m$ 的编码(通常将 $m$ 编码为群元素)。
安全分析
| 属性 | 保证 | 依赖假设 |
|---|---|---|
| 绑定性 | 完美绑定 | 群上离散对数唯一性 |
| 隐藏性 | 计算隐藏 | DDH 假设(Decisional Diffie-Hellman) |
承诺方案的组合与扩展
同态承诺(Homomorphic Commitment)
Pedersen 承诺具有加法同态性:
$$\mathsf{Commit}(m_1; r_1) \cdot \mathsf{Commit}(m_2; r_2) = \mathsf{Commit}(m_1 + m_2; r_1 + r_2)$$
证明:
$$g^{m_1} h^{r_1} \cdot g^{m_2} h^{r_2} = g^{m_1+m_2} h^{r_1+r_2} = \mathsf{Commit}(m_1+m_2; r_1+r_2)$$
这一性质在保密电子投票和隐私计算中极为重要:可以在不打开单个承诺的情况下计算聚合结果。
向量承诺(Vector Commitment)
向量承诺允许承诺一个向量 $\vec{v} = (v_1, \ldots, v_n)$,并支持对每个分量 $v_i$ 的打开证明。Merkle 树是向量承诺的一个特例。
多项式承诺(Polynomial Commitment)
多项式承诺允许承诺一个多项式 $f(X) = \sum_{i=0}^d a_i X^i$,并支持验证 $f(z) = y$ 的声明。KZG10 承诺(Kate-Zaverucha-Goldberg)是 zk-SNARK 的核心组件。
国密标准映射
哈希承诺与 GM/T 0004-2012
SM3 密码杂凑算法(GM/T 0004-2012)可用于构建安全的哈希承诺。其 256-bit 输出提供 128-bit 抗碰撞安全性,满足计算绑定要求。
Pedersen 承诺与 GB/T 32918-2016
SM2 椭圆曲线(GB/T 32918.5-2016 参数定义)为 Pedersen 承诺提供了所需的循环群结构。该曲线通过 ISO/IEC 14888-3:2018/Amd 1 国际标准化,具备国际认可的安全基础。
密码敏捷性要求
GM/T 0054-2018《信息系统密码应用基本要求》第三级要求中明确:"应采用密码技术保证重要数据在传输和存储过程中的机密性"。承诺方案作为机密性和完整性的基础组件,其实现应符合 GM/T 0054-2018 的相关要求。
安全性证明框架
绑定性的形式化证明
承诺方案的绑定性通常通过游戏跳跃(Game Hopping)技术证明:
- 定义安全游戏:敌手 $\mathcal{A}$ 输出承诺 $c$ 和两个打开值 $(m, r), (m', r')$
- 绑定实验:$\text{Bind}_{\mathcal{A}}(\lambda) = 1$ 当且仅当 $m \neq m'$ 且 $\mathsf{Open}(c, m, r) = \mathsf{Open}(c, m', r') = 1$
- 安全定义:若对于所有 PPT 敌手 $\mathcal{A}$,$\Pr[\text{Bind}_{\mathcal{A}}(\lambda) = 1] \leq \text{negl}(\lambda)$,则方案满足计算绑定性
隐藏性的形式化证明
隐藏性通过不可区分性游戏证明:
- 实验 0:敌手选择 $m_0, m_1$,挑战者返回 $\mathsf{Commit}(m_0)$
- 实验 1:敌手选择 $m_0, m_1$,挑战者返回 $\mathsf{Commit}(m_1)$
- 安全定义:若敌手区分实验 0 和实验 1 的优势可忽略,则方案满足计算隐藏性
工程实现建议
随机数质量
承诺方案的安全性严重依赖盲化因子 $r$ 的质量。必须使用密码学安全的伪随机数生成器(CSPRNG):
- Python:
os.urandom()或secrets.token_bytes() - 符合 GM/T 0005-2012《随机性检测规范》的随机数源
参数生成
Pedersen 承诺的第二生成元 $H$ 必须通过可验证随机过程生成,确保无人知道 $\alpha$($H = [\alpha]G$ 中的离散对数)。常用方法:
- Hash-to-Curve:$H = \text{HashToCurve}(\text{"commitment\_base"})$
- 多方计算:多个参与方联合生成,确保只要一方诚实,$\alpha$ 就未知
侧信道防护
椭圆曲线上的承诺实现需注意:
- 标量乘法使用恒定时间算法(防止计时攻击)
- 随机数 $r$ 应满足均匀分布(防止偏差攻击)
- 大数运算使用经过验证的密码学库
总结
密码学承诺方案是现代密码协议的基础原语,其核心价值在于:
| 特性 | 说明 |
|---|---|
| 通用性 | 构建 ZKP、MPC、安全拍卖、数字投票的必备组件 |
| 可组合性 | 同态承诺支持密文上的计算 |
| 形式化安全 | 清晰的绑定/隐藏性定义与证明框架 |
| 国密兼容 | 可基于 SM3/SM2 构建合规的承诺方案 |
参考来源
- Blum, M. (1982). "Coin Flipping by Telephone". *Advances in Cryptology — CRYPTO '82*.
- Pedersen, T.P. (1991). "Non-Interactive and Information-Theoretic Verifiable Secret Sharing". *Advances in Cryptology — CRYPTO '91*.
- GM/T 0004-2012《SM3 密码杂凑算法》. 国家密码管理局.
- GB/T 32918-2016《SM2 椭圆曲线公钥密码算法》. 国家标准化管理委员会.
- GM/T 0003.5-2012《SM2 椭圆曲线公钥密码算法 第5部分:参数定义》.
- Goldreich, O. (2001). *Foundations of Cryptography: Basic Tools*. Cambridge University Press.
- GM/T 0054-2018《信息系统密码应用基本要求》.
- Kate, A., Zaverucha, G.M., Goldberg, I. (2010). "Constant-Size Commitments to Polynomials and Their Applications". *ASIACRYPT 2010*.