ECDSA安全漏洞剖析:从非ce泄露到密钥恢复实战
DSA基础
ECDSA是基于椭圆曲线的数字签名算法(DSA)变种。DSA包含三个核心算法:
- 密钥生成:随机选择私钥x,计算公钥y = gˣ mod p
- 签名生成:选择随机数k(nonce),计算r = (gᵏ mod p) mod q,s = k⁻¹(H(m) + xr) mod q
- 签名验证:验证r = (gᴴ⁽ᵐ⁾yʳ)ˢ⁻¹ mod p mod q
ECDSA的致命弱点
非ce重用攻击
若两个签名使用相同nonce k:
k = (s₁ - s₂)⁻¹(H(m₁) - H(m₂))
x = r⁻¹(ks - H(m))
部分比特泄露攻击
- 仅泄露3个nonce比特即可破解160位DSA
- LadderLeak攻击表明:泄露<1比特即可恢复密钥
- 随机数生成器仅4比特偏差也能导致256位ECDSA被攻破
实战格攻击(100行Python)
import ecdsa, olll
# 生成含偏差nonce的签名
gen = ecdsa.NIST256p.generator
order = gen.order()
priv_key = ecdsa.ecdsa.Private_key(pub_key, secret)
nonces = [random.getrandbits(128) + (fixed_bits << 128) for _ in range(6)]
sigs = [priv_key.sign(msgs[i], nonces[i]) for i in range(6)]
# 构建格矩阵
matrix = [
[order, 0, 0, 0],
[0, order, 0, 0],
[r1*s1_inv, r2*s2_inv, 2^128/order, 0],
[m1*s1_inv, m2*s2_inv, 0, 2^128]
]
# LLL格基约简
new_matrix = olll.reduction(matrix, 0.75)
# 从格向量恢复私钥
for row in new_matrix:
potential_key = (rns1 - r1sn)⁻¹ * (snm1 - s1mn - s1sn*k_diff)
if verify(potential_key):
print("密钥恢复成功!")
防护措施
- 首选EdDSA:内置确定性nonce生成
- RFC 6979:确定性nonce生成标准
- 恒定时间实现:防止侧信道泄露
- 随机数增强:避免偏差产生
本文演示的攻击在以下场景有效:
- Nonce重用(100%成功率)
- 80比特固定nonce(需5个签名)
- 仅4比特偏差(需约4000个签名)
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码