You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ethers.js中recoverPublicKey能否用于ECDSA签名验证?

关于ECDSA签名验证与ethers.js recoverPublicKey的疑问解答

核心结论

直接对比原公钥与ethers.utils.recoverPublicKey(digest, signature)的返回值是可行的,但需要注意公钥格式的一致性。

关键细节解析

  • 所谓“一个私钥对应多个公钥”,实际是公钥的两种编码格式:

    • 非压缩公钥:65字节,以0x04开头,后跟x、y坐标各32字节
    • 压缩公钥:33字节,以0x02或0x03开头,仅包含x坐标,y坐标的奇偶性由前缀标识
      这两种格式只是同一公钥的不同表示,本质指向椭圆曲线上的同一个点。
  • SEC1规范提到的“多个候选公钥”是签名恢复的中间状态:
    理论上,ECDSA签名恢复过程可能生成4个候选公钥点,但签名中的v值(恢复ID)会明确指定正确的那个。ethers.js的recoverPublicKey函数会利用签名中的v值直接返回对应正确的公钥,不会返回多个候选结果。

验证注意事项

  • 必须保证原公钥与恢复出的公钥格式一致:
    如果你的原公钥是压缩格式,需要先转为非压缩格式再对比;可以用ethers.utils.computePublicKey统一格式:
    // 将压缩公钥转为非压缩格式
    const uncompressedPubKey = ethers.utils.computePublicKey(compressedPubKey, false);
    // 对比验证
    const isValid = uncompressedPubKey === ethers.utils.recoverPublicKey(digest, signature);
    
  • 若签名是仅包含r+s的原始格式,需要先补充正确的v值才能恢复正确公钥,但ethers.js处理的标准签名(65字节)通常已包含v值。

更简便的替代验证方式

如果担心格式问题,可直接使用ethers.utils.verifyDigest函数,它会直接验证签名是否匹配指定公钥,无需手动对比:

const isValid = ethers.utils.verifyDigest(digest, signature, publicKey);

内容的提问来源于stack exchange,提问作者Luis F.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:35:26