以太坊:恶意篡改交易数据后签名仍可验证的问题排查
问题原因与解决方案:篡改交易后ECDSA验证仍通过的误区
问题本质
你遇到的是ECDSA签名恢复机制的正常特性,并非代码bug:
recoverPublicKey的核心逻辑是:给定任意签名和任意哈希值,计算出一个公钥,使得该公钥对该哈希的签名恰好是传入的签名。- 当你用篡改后的
hashEvil恢复公钥时,得到的pkEvil本身就是为hashEvil和现有签名生成的匹配公钥,验证自然会返回true——但这个公钥和原始发送方的公钥完全无关,不能证明签名的有效性。
正确的验证流程
在以太坊等真实场景中,验证签名的核心是使用已知的发送方公钥(或通过地址推导的公钥),而非从签名恢复的公钥来验证:
修正后的验证代码
// 接收方预先知晓发送方的公钥(以太坊中可通过发送方地址反推) const knownSenderPublicKey = publicKey; // 接收方收到篡改后的交易,重新计算哈希 const dataEvil = "modified"; const hashEvil = keccak256(utf8ToBytes(dataEvil)); // 用原始公钥验证签名与篡改后哈希的匹配性 console.log('verified evil:', secp256k1.verify(signature, hashEvil, knownSenderPublicKey)); // false,符合预期
真实场景的防护逻辑
在以太坊生态中,交易的发送方地址由公钥推导而来,接收方会遵循以下流程:
- 从交易中提取发送方地址
- 通过地址反推对应的公钥(地址是公钥keccak256哈希的后20字节)
- 用该公钥验证交易哈希与签名的匹配性
这种方式下,篡改交易后用原始公钥验证必然失败,因为签名是针对原始交易哈希生成的,与篡改后的哈希完全不匹配。
内容的提问来源于stack exchange,提问作者lcnicolau
相关产品推荐
相关产品推荐

