如何用Python的ecdsa库验证71字节的ECDSA签名
问题:验证71字节ECDSA签名时出现长度错误
我尝试用Python的ecdsa库验证一个71字节的ECDSA签名,代码如下:
import ecdsa from hashlib import sha256 sig = bytes.fromhex("3045022100C63ECC434A7D78DA9CCB8328BF87564FE1DF3F1F879E5C578DDF4637AE7C47790220266BC4491EA8FCF740DA00F14CCA1E67D9A7EADD48BC24D033499879A17D1BF7") message = bytes.fromhex("0A8163888A52B2C873DD3730DED740B5FA4373438BC129E65CA8E9F955DA5FB3") pubKey = '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(pubKey), curve=ecdsa.SECP256k1, hashfunc=sha256) assert vk.verify(sig, message)
运行后报错:
ecdsa.keys.BadSignatureError: ('Malformed formatting of signature', MalformedSignature('Invalid length of signature, expected 64 bytes long, provided string is 71 bytes long'))
解决方案
你的71字节签名是ASN.1 DER编码格式,而ecdsa库的verify方法默认接受的是64字节的r和s直接拼接的紧凑格式。只需调整签名的解码方式即可完成验证,有两种简洁的实现方式:
方法1:直接指定DER解码参数
调用verify时传入sigdecode=ecdsa.util.sigdecode_der,让库自动解析DER格式的签名:
import ecdsa from hashlib import sha256 sig = bytes.fromhex("3045022100C63ECC434A7D78DA9CCB8328BF87564FE1DF3F1F879E5C578DDF4637AE7C47790220266BC4491EA8FCF740DA00F14CCA1E67D9A7EADD48BC24D033499879A17D1BF7") message = bytes.fromhex("0A8163888A52B2C873DD3730DED740B5FA4373438BC129E65CA8E9F955DA5FB3") pubKey = '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(pubKey), curve=ecdsa.SECP256k1, hashfunc=sha256) # 直接验证DER格式签名,指定解码规则 assert vk.verify(sig, message, sigdecode=ecdsa.util.sigdecode_der)
方法2:手动转换为紧凑格式
先解析DER签名得到r和s,再拼接成64字节的紧凑格式后验证:
import ecdsa from hashlib import sha256 sig = bytes.fromhex("3045022100C63ECC434A7D78DA9CCB8328BF87564FE1DF3F1F879E5C578DDF4637AE7C47790220266BC4491EA8FCF740DA00F14CCA1E67D9A7EADD48BC24D033499879A17D1BF7") message = bytes.fromhex("0A8163888A52B2C873DD3730DED740B5FA4373438BC129E65CA8E9F955DA5FB3") pubKey = '02b4632d08485ff1df2db55b9dafd23347d1c47a457072a1e87be26896549a8737' vk = ecdsa.VerifyingKey.from_string(bytes.fromhex(pubKey), curve=ecdsa.SECP256k1, hashfunc=sha256) # 解析DER签名为r、s参数 r, s = ecdsa.util.sigdecode_der(sig, vk.curve.order) # 转换为64字节紧凑格式签名 compact_sig = ecdsa.util.sigencode_string(r, s, vk.curve.order) # 验证紧凑格式签名 assert vk.verify(compact_sig, message)
两种方法都能解决签名长度不匹配的问题,方法1更简洁高效,推荐优先使用。
内容的提问来源于stack exchange,提问作者MJay
相关产品推荐
相关产品推荐

