Lec 5 数字签名:基于哈希
MIT 6.1600 · Introduction to Computer Security
TL;DR
- 数字签名把秘密签名密钥与公开验证密钥分开,使任何人都能验证而只有签名者能产生新签名,安全目标仍是 EUF-CMA。
- Lamport 一次签名以公开哈希原像实现量子攻击下仍可信的签名,但密钥和签名体积大,且同一密钥不能重复使用。
- Winternitz 用计算换取更短签名,Merkle 树把大量一次性公钥压缩为单个根;现代 XMSS、LMS 与 SPHINCS+ 延续这条设计路线。
1. 为什么需要数字签名
MAC 使用对称密钥,只有知道密钥的人才能验证——验证者即可伪造者。
数字签名提供非对称方案:
- 私钥 sk:签名者持有,秘密
- 公钥 vk:任何人都可验证,公开
σ←Sign(sk,m)b←Verify(vk,m,σ)
不可否认性(Non-repudiation):签名者事后无法否认,因为只有他知道 sk。
2. 安全定义:EUF-CMA
与 MAC 相同的游戏,但密钥为非对称:
- 挑战者生成 (sk,vk)←KeyGen(1λ),公布 vk
- 对手 A(vk) 自适应查询 Sign(sk,⋅) oracle
- A 输出 (m∗,σ∗)
胜利:Verify(vk,m∗,σ∗)=1 且 m∗∈/Q
Pr[A wins EUF-CMA]≤negl(λ)
3. 基于哈希的签名:Lamport 一次签名
3.1 密钥生成
对每个消息位 i∈{1,…,n}:
sk:xi,0,xi,1${0,1}λ
vk:yi,b=H(xi,b)∀ i,b∈{0,1}
私钥:2n 个随机值 {xi,b}
公钥:2n 个哈希值 {yi,b}
3.2 签名
对消息 m=m1m2…mn∈{0,1}n:
σ=(x1,m1, x2,m2, …, xn,mn)
即:对每一位 mi,公开 xi,mi(另一个 xi,1−mi 保密)。
3.3 验证
收到 (m,σ=(z1,…,zn)) 后,验证:
∀i: H(zi)=?yi,mi
3.4 安全性分析
若要伪造消息 m′(某位 mi′=mi),需知道 xi,mi′——但从公钥 yi,mi′=H(xi,mi′) 反推 xi,mi′ 需破解预像抗性。
因此 Lamport 签名安全性基于:CRHF 的预像抗性。
3.5 关键限制
一次性(One-time):私钥每对 (xi,0,xi,1) 中公开一个后,另一个也间接可推断——不能用同一私钥签名两次!
否则攻击者可组合两个签名伪造其他消息。
密钥/签名较大:n=256 时,私钥、公钥各 512×λ bits,签名 256×λ bits。
4. Winternitz 签名(改进 Lamport)
核心思想
将消息 n 位分成 w 位一组处理(w 为 Winternitz 参数),每组用哈希链代替单次哈希:
ski${0,1}λ,vki=H2w(ski)
签名第 i 组(值为 vi)时:
σi=Hvi(ski)
验证:
H2w−vi(σi)=?vki
优势:密钥/签名大小减少 w 倍,代价是验证计算增加。
5. 哈希树签名:Merkle 签名方案(MSS)
解决 Lamport 的一次性问题
Merkle 树允许用一个公钥支持 2h 次签名(h 为树高):
生成 2h 对 Lamport 密钥对 (ski,vki)
以所有 vki 为叶节点构建 Merkle 树,根 root 作为最终公钥。
第 i 次签名:
- 用 ski 签名消息,得 σLamport
- 提供 vki 和 Merkle 树认证路径(h 个兄弟节点)
验证:
- 验证 Lamport 签名 σLamport 在 vki 下合法
- 验证 vki 在 Merkle 树中的认证路径通向 root(公钥)
签名大小
∣σ∣=∣σLamport∣+h⋅λ
认证路径长度 O(log2h)=O(h)。
6. 现代基于哈希的签名方案
| 方案 | 特点 |
|---|
| XMSS | 有状态,需跟踪已用密钥索引,RFC 8391 |
| SPHINCS+ | 无状态(多层 Merkle + 随机化),NIST PQC 标准 |
SPHINCS+ 优势:不需要维护状态(不担心重用密钥),代价是签名较大(约 8–49 KB)。
7. 后量子安全性
经典方案(RSA、ECDSA)依赖整数分解/离散对数——量子计算机可用 Shor 算法破解。
基于哈希的签名安全性仅依赖哈希函数的预像抗性,量子计算机对预像抗性的攻击优势仅为 Grover 算法提供的 加速——增加哈希输出长度即可抵抗。
SHA-512 预像抗性 vs 量子:2512/2=2256 次量子操作,仍安全
关键公式
Lamport 签名:
σi=xi,mi,验证:H(σi)=?yi,mi
Merkle 认证路径验证(叶节点 vkj,路径 π1,…,πh):
h0=H(vkj),hk+1=H(hk∥πk+1) 或 H(πk+1∥hk)
接受当且仅当 hh=root
我的理解
一次性签名的难点不仅是数学构造,更是状态管理;一旦重复使用密钥,证明中的安全前提就被实现层破坏。