求助:AWS KMS存储的以太坊账户私钥哈希签名结果异常
解决AWS KMS签署以太坊哈希的问题
核心问题分析
你遇到的问题源于两个关键错误:
- 以太坊签名要求对keccak256哈希进行签名,而非你当前使用的sha256
- 对AWS KMS返回的签名解析及v值处理不符合以太坊规范
另外,ECDSA签名每次生成不同结果是正常现象(签名过程使用随机k值),但错误的哈希算法和v值处理会导致签名无法正确恢复出你的以太坊地址。
修正后的实现代码
import boto3 from eth_keys import keys from eth_utils import keccak from ethereum_kms_signer import kms as signer_utils KEY_ID = 'AWS KEY ID' DATA = 'SOME DATA' # 初始化KMS客户端 kms_client = boto3.client('kms', # 填入你的AWS凭证配置,比如aws_access_key_id、aws_secret_access_key、region_name等 ) # 1. 生成以太坊规范的keccak256哈希(直接传字节,无需hex编码) message_bytes = DATA.encode('utf-8') eth_hash = keccak(message_bytes) # 2. 调用KMS签名,注意参数匹配 signature_response = kms_client.sign( KeyId=KEY_ID, Message=eth_hash, SigningAlgorithm='ECDSA_SHA_256', MessageType='DIGEST' # 明确告知KMS传入的是已哈希的摘要 ) # 3. 获取符合以太坊规范的r、s、v值 address = signer_utils.get_eth_address(KEY_ID, kms_client) r, s, v = signer_utils.get_sig_r_s_v(eth_hash, signature_response['Signature'], address) # 4. 生成以太坊标准十六进制签名 sig = keys.Signature(vrs=(v, r, s)).to_hex() print(f"签名结果: {sig}") print(f"对应以太坊地址: {address}")
关键细节说明
- 哈希算法替换:以太坊所有签名操作基于keccak256(非SHA-256),必须使用
eth_utils.keccak生成哈希,否则签名无法被以太坊生态验证。 - KMS参数校验:
MessageType='DIGEST'必须和传入的Message是哈希值对应,避免KMS重复哈希SigningAlgorithm='ECDSA_SHA_256'是P256K1密钥对应的正确算法
- v值校正:以太坊的v值固定为27或28,
get_sig_r_s_v方法会结合哈希和地址校正KMS返回的原始v值,这是确保签名能恢复出正确地址的核心步骤。 - 签名随机性:每次签名结果不同是ECDSA的正常特性,只要能恢复出正确的以太坊地址,签名就是有效的。
签名验证方法
你可以用以下代码验证签名有效性:
from eth_account.messages import encode_defunct from eth_account import Account # 生成以太坊标准消息结构 message = encode_defunct(text=DATA) # 从签名恢复地址 recovered_address = Account.recover_message(message, signature=sig) print(f"恢复的地址: {recovered_address}") print(f"地址匹配: {recovered_address.lower() == address.lower()}")
若输出地址匹配为True,说明签名符合以太坊规范。
内容的提问来源于stack exchange,提问作者ICJP
相关产品推荐
相关产品推荐

