基于指定ECDSA曲线,如何利用两个签名推导私钥?
利用自定义ECDSA曲线从两个签名推导私钥
首先明确:你给出的曲线参数就是secp256k1(比特币采用的标准椭圆曲线),无需额外实现自定义曲线的底层逻辑,直接用现成的椭圆曲线工具即可完成私钥推导。
核心原理
ECDSA签名的核心公式为:s = k⁻¹(h + d*r) mod p
其中:
k是签名用的一次性非ce(必须唯一,重复使用会直接泄露私钥)h是消息的哈希值d是目标私钥r是签名的一部分(等于k*G的x坐标取模p)
如果同一个k被用于两个不同消息的签名,得到(r,s₁)和(r,s₂),对应哈希h₁和h₂,联立两个公式可解出私钥:d = (s₁*h₂ - s₂*h₁) * (s₂ - s₁)⁻¹ mod p
代码实现(基于SageMath)
直接复用你给出的曲线定义,代入实际签名参数即可:
# 定义secp256k1曲线(你的参数) q = 115792089237316195423570985008687907853269984665640564039457584007908834671663 A = 0 B = 0x07 F = GF(q) E = EllipticCurve(F,[A,B]) Gx = 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 Gy = 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 G = E(Gx,Gy) p = 115792089237316195423570985008687907852837564279074904382605163141518161494337 assert G.order() == p # 替换为你实际获取的参数 h1 = 0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef # 第一个消息哈希(取模p后) h2 = 0xabcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890 # 第二个消息哈希(取模p后) r = 0x9876543210fedcba9876543210fedcba9876543210fedcba9876543210fedcba # 两个签名共享的r值 s1 = 0x112233445566778899aabbccddeeff00112233445566778899aabbccddeeff00 # 第一个签名的s值 s2 = 0x00ffeeddccbbaa99887766554433221100ffeeddccbbaa998877665544332211 # 第二个签名的s值 # 计算私钥d numerator = (s1 * h2 - s2 * h1) % p denominator = (s2 - s1) % p d = (numerator * inverse_mod(denominator, p)) % p # 验证私钥正确性 public_key = d * G # 验证签名1 u1 = (h1 * inverse_mod(s1, p)) % p u2 = (r * inverse_mod(s1, p)) % p assert (u1 * G + u2 * public_key).x() == r, "签名1验证失败" # 验证签名2 u1 = (h2 * inverse_mod(s2, p)) % p u2 = (r * inverse_mod(s2, p)) % p assert (u1 * G + u2 * public_key).x() == r, "签名2验证失败" print(f"推导得到的私钥:{hex(d)}")
关键注意事项
- 必须满足两个签名使用了同一个非ce k,否则无法推导私钥;
- 消息哈希
h1、h2需要取模p(通常是对消息做SHA-256哈希后,将哈希值转为整数再取模p); - 如果你的签名是DER编码格式,需要先解析出
r和s的原始整数; - 若使用Python标准库,可借助
ecdsa库(内置secp256k1曲线),逻辑与上述代码一致,仅需调整库的API调用方式。
内容的提问来源于stack exchange,提问作者Maximilian Tempo
相关产品推荐
相关产品推荐

