You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何基于签名和消息推导ECDSA公钥 适配SECP256k1曲线

实现方案

ECDSA 签名本质是(r, s)二元组,仅靠(r,s)和原始消息最多可以推导出4个候选公钥,需要额外的*恢复标识符(recovery id,取值0/1/2/3)*才能唯一确定正确公钥。如果没有提前保存恢复id,也可以遍历所有候选公钥,通过验签逻辑筛选出正确的那一个。

方案1:使用原生ecdsa库实现

无需额外安装其他依赖,和你现有代码的兼容性最好:

from ecdsa import SigningKey, SECP256k1, VerifyingKey
from ecdsa.util import sigdecode_string
import hashlib

def vk_from_signature(signature: bytes, msg: bytes, curve=SECP256k1, hashfunc=hashlib.sha256) -> VerifyingKey:
    # 计算消息哈希,必须和签名时使用的哈希算法完全一致
    msg_hash = hashfunc(msg).digest()
    r, s = sigdecode_string(signature, curve.order)
    # 遍历所有可能的恢复标识符
    for recid in range(4):
        try:
            vk = VerifyingKey.from_public_key_recovery(
                signature, msg_hash, curve=curve, recid=recid, hashfunc=hashfunc
            )
            # 验签确认公钥正确性
            if vk.verify(signature, msg, hashfunc=hashfunc):
                return vk
        except:
            continue
    raise ValueError("无法从给定签名和消息恢复出有效公钥")

# 原有签名逻辑调整,统一哈希算法避免歧义
sk = SigningKey.generate(curve=SECP256k1)
vk = sk.verifying_key
msg = b"Some arbitrary message"
signature = sk.sign(msg, hashfunc=hashlib.sha256)

print("原始公钥: ", vk.to_string().hex())
# 恢复公钥
vk2 = vk_from_signature(signature, msg)
print("恢复得到的公钥: ", vk2.to_string().hex())

if vk.to_string().hex() == vk2.to_string().hex():
    print("SUCCESS")

方案2:使用coincurve库实现(仅针对SECP256k1曲线)

如果你只需要用到SECP256k1曲线,这个专门优化过的库效率更高,实现更简单:

  1. 先安装依赖:pip install coincurve
  2. 代码实现:
from coincurve import PrivateKey, PublicKey

# 签名逻辑
sk = PrivateKey()
vk = sk.public_key
msg = b"Some arbitrary message"
# 生成带恢复标识符的签名(65字节,最后1字节为恢复id)
signature_with_recid = sk.sign_recoverable(msg)

# 公钥恢复逻辑
def vk_from_signature(signature: bytes, msg: bytes) -> PublicKey:
    return PublicKey.from_signature_and_message(signature, msg, hasher=None)

# 测试
vk2 = vk_from_signature(signature_with_recid, msg)
print("原始公钥: ", vk.format().hex())
print("恢复得到的公钥: ", vk2.format().hex())
if vk.format() == vk2.format():
    print("SUCCESS")

内容的提问来源于stack exchange,提问作者Shatnerz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 23:06:04