python-ecdsa生成的ECDSA签名长度是否符合预期?
为什么python-ecdsa生成的签名是64字节,而Bitcoin Wiki说71-73字节?
嘿,这个差异完全是因为签名格式不同导致的,咱们把这事掰明白:
1. python-ecdsa默认输出的是「原始ECDSA签名」
你用private_key.sign(b'message')得到的64字节签名,是最基础的ECDSA签名形式:它直接把签名里的两个核心整数r和s各以32字节的形式拼接在一起(因为Secp256k1的阶是256位,刚好对应32字节),所以总长度就是32+32=64字节。这是库的默认输出格式,完全符合ECDSA的数学定义,但不是比特币网络实际使用的格式。
2. Bitcoin Wiki提到的是「DER编码后的ECDSA签名」
比特币系统里用的签名是经过DER(Distinguished Encoding Rules)编码的,这是一种ASN.1标准的编码格式,目的是让签名结构更明确、能被不同系统解析。DER编码会给r和s加上额外的标识信息,比如:
- 开头的
0x30标记这是一个序列 - 后续字节表示整个序列的总长度
- 分别给
r和s加上类型标识(0x02)、长度标识 - 如果
r或s的最高位是1,还会额外补一个0x00来避免被解析成负数,这就导致r或s的长度可能变成33字节
这些额外的编码字节加起来,就使得DER签名的总长度在71-73字节之间浮动(取决于r和s是否需要补0)。
3. 如何用python-ecdsa生成比特币兼容的DER签名?
你只需要把原始签名转换成DER格式就行,有两种简单的方法:
方法一:从原始签名编码成DER
from ecdsa import SigningKey, SECP256k1, util private_key = SigningKey.generate(curve=SECP256k1) # 生成原始64字节签名 raw_sig = private_key.sign(b'message') # 拆分r和s,编码成DER格式 der_sig = util.sigencode_der(raw_sig[:32], raw_sig[32:], SECP256k1.order) print(f"DER签名长度: {len(der_sig)}") # 输出71-73之间的数值
方法二:直接生成DER格式签名
用sign_deterministic方法并指定编码方式(推荐,因为确定性签名更符合比特币的规范):
from ecdsa import SigningKey, SECP256k1, util private_key = SigningKey.generate(curve=SECP256k1) # 直接生成DER编码的签名 der_sig = private_key.sign_deterministic(b'message', sigencode=util.sigencode_der) print(f"DER签名长度: {len(der_sig)}")
总结
你既没理解错Wiki内容,也不是用错了库——只是两者讨论的是ECDSA签名的不同表现形式:一个是原始的数学形式,一个是比特币网络使用的标准化编码形式。
内容的提问来源于stack exchange,提问作者zrbecker
相关产品推荐
相关产品推荐

