使用Python ECDSA库处理AWS KMS签名时遇到的错误
AWS KMS ECDSA签名与ecdsa库兼容问题解决
问题根源
AWS KMS返回的ECDSA签名是ASN.1 DER编码格式,而你使用的ecdsa库在恢复公钥时,需要的是64字节的P1363格式(r和s各32字节直接拼接)。直接截取前64字节相当于破坏了签名的结构,运气好时刚好截到完整的r+s组合,运气差则会导致解析出的参数不符合椭圆曲线规则,触发平方根错误。
正确解决方法
不用盲目截断,把KMS返回的DER签名转换成P1363格式即可,步骤如下:
1. 安装解析DER的依赖
先安装pyasn1库用于解析ASN.1编码:
pip install pyasn1
2. 修改签名生成方法
在你的sign_msg_hash方法中添加转换逻辑:
from pyasn1.codec.der import decoder from pyasn1.type.univ import Sequence, Integer def sign_msg_hash(self, msg_hash: HexBytes): signature = self._kms_client.sign( KeyId=self._key_id, Message=msg_hash, MessageType="DIGEST", SigningAlgorithm="ECDSA_SHA_256", ) der_sign = signature["Signature"] # 解析DER格式签名,提取r和s参数 decoded_seq, _ = decoder.decode(der_sign, asn1Spec=Sequence()) r = decoded_seq[0].asInteger() s = decoded_seq[1].asInteger() # 将r和s转为32字节大端格式,拼接成64字节的P1363标准签名 r_bytes = r.to_bytes(32, byteorder='big') s_bytes = s.to_bytes(32, byteorder='big') p1363_sign = r_bytes + s_bytes return p1363_sign
3. 验证代码无需修改
现在直接使用转换后的签名调用公钥恢复方法即可正常运行:
sign = kms.sign_msg_hash(transaction) vks = ecdsa.VerifyingKey.from_public_key_recovery_with_digest( sign, transaction, curve=ecdsa.SECP256k1, hashfunc=sha256 )
补充说明
DER编码的签名带有结构标识,包含r和s的长度信息,所以总长度会在70-72字节浮动。直接截断会混入结构标识或r/s的不完整字节,导致解析出的参数不符合椭圆曲线数学规则,才会触发平方根错误。必须通过ASN.1解析工具正确提取r和s,再转换成目标格式。
内容的提问来源于stack exchange,提问作者whitebat 199
相关产品推荐
相关产品推荐

