以太坊的ecrecover预编译合约

1. 引言

前序博客:

ECDSA,全称为Elliptic curve Digital Signature Algorithm,采用Elliptic curve cryptography来实现的数字签名算法。

公私钥对 ( p k , P ) (pk,P) (pk,P),其中公钥 P = p k × G P=pk\times G P=pk×G G G G为所选椭圆曲线的base point。(elliptic curve base point: a point on the curve that generates a subgroup of large prime order n n n n × G = O n\times G=\mathcal{O} n×G=O, O \mathcal{O} O is the identity element。)

1.1 ECDSA签名

ECDSA对消息 m m m的签名流程为:

  • 1)计算消息 m m m的hash值: e = h a s h ( m ) e=hash(m) e=hash(m)。(hash函数可为SHA-2,输出转换为数值。)
  • 2)若group order n n n的bit length为 L n L_n Ln,则取 e e e值最左侧的 L n L_n Ln bits赋值给 z z z。(注意, z z z值可以比 n n n大,但bit length不能比 n n n的长。)
  • 3)选择随机数 k ∈ R [ 1 , n − 1 ] k\in_R [1,n-1] kR[1,n1]。(注意,不信任一般的随机数生成器,因为不好的RNG有太多的failures和vulnerabilities,可采用RFC6979 根据 p k pk pk m m m来计算deterministic k k k。)(如:2013年8月,安卓Bit0coin钱包因使用了错误的随机数生成器,引起私钥泄露,导致资金损失;2010年12月,索尼PS3游戏机因错误的使用了静态而不是随机的 k k k值,导致其ECDSA私钥泄露。)
  • 4)计算curve point ( x 1 , y 1 ) = k × G (x_1,y_1)=k\times G (x1,y1)=k×G
  • 5)计算 r = x 1 m o d    n r=x_1\mod n r=x1modn,若 r = 0 r=0 r=0,则跳转继续执行步骤3)。
  • 6)计算 s = ( z + r ⋅ p k ) / k m o d    n s=(z+r\cdot pk)/k \mod n s=(z+rpk)/kmodn,若 s = 0 s=0 s=0,则跳转继续执行步骤3)。
  • 7)最终的签名为 ( r , s ) (r,s) (r,s)。(注意, ( r , − s m o d    n ) (r,-s\mod n) (r,smodn)也为有效签名。)
    【根据 BIP-62 以及EIP-2可知,为了解决ECDSA签名的malleability问题,可对签名中的 s s s值进行约束,限定 s s s值不高于曲线order的一半。】

整个ECDSA签名流程中,要求:

  • k k k值应为secret。
  • 不同的签名应选择不同的 k k k值,否则会泄露私钥 p k pk pk
    在这里插入图片描述

1.2 ECDSA验签

对收到的签名 ( r , s ) (r,s) (r,s),采用公钥 P P P进行验签的流程为:

  • 1)验证公钥 P P P不等于identity element O \mathcal{O} O,且为其坐标为valid。
  • 2)验证公钥 P P P lies on the curve。
  • 3)验证公钥 P P P的order为 n n n,即 n × P = O n\times P=\mathcal{O} n×P=O
  • 4)验证签名 ( r , s ) (r,s) (r,s)有效,即满足 r ∈ [ 1 , n − 1 ] , s ∈ [ 1 , n − 1 ] r\in [1,n-1],s\in [1,n-1] r[1,n1],s[1,n1]
  • 5)计算消息 m m m的hash值,所采用的hash函数应与签名时一致。 e = h a s h ( m ) e=hash(m) e=hash(m)
  • 6)取 e e e的最左侧 L n L_n Ln bits赋值给 z z z
  • 7)计算 u 1 = z / s m o d    n , u 2 = r / s m o d    n u_1=z/s\mod n,u_2=r/s\mod n u1=z/smodn,u2=r/smodn
  • 8)计算curve point ( x 1 , y 1 ) = u 1 × G + u 2 × P (x_1,y_1)=u_1\times G+u_2\times P (x1,y1)=u1×G+u2×P。若 ( x 1 , y 1 ) = O (x_1,y_1)=\mathcal{O} (x1,y1)=O,则签名无效。
  • 9)若 r ≡ x 1 ( m o d    n ) r\equiv x_1(\mod n) rx1(modn)成立,则签名有效,否则签名无效。

注意,以上ECDSA验签算法可做如下改进:

  • 只计算一次 1 / s m o d    n 1/s\mod n 1/smodn
  • 使用Shamir’s trick,a sum of two scalar multiplication u 1 × G + u 2 × P u_1\times G+u_2\times P u1×G+u2×P can be calculated faster than two scalar multiplications done independently。(参考2014年论文《The Double-Base Number System in Elliptic Curve Cryptograhy》)

ECDSA总的签名和验签流程可以如下图示意:
在这里插入图片描述

1.3 ECDSA的public key recovery

ECDSA也支持public key recovery算法,前提是提前知道签名方的公钥或者公钥hash值,否则有可能恢复出错误的公钥信息。
在这里插入图片描述

以太坊在0x01地址实现了ecrecover预编译合约,其函数原型为:

function ecrecover(bytes32 hash, bytes8 v, bytes32 r, bytes32 s) returns (address);

ecrecover会返回 根据给定的签名计算ECDSA recovery函数获得的地址address。
solidity合约中的调用示例为:

function recoverSignerFromSignature(uint8 v, bytes32 r, bytes32 s, bytes32 hash) external {
    address signer = ecrecover(hash, v, r, s);
    require(signer != address(0), "ECDSA: invalid signature");
}

在以太坊交易中,最后的65字节为ecdsa签名,依次为:

  • 32字节的 r r r
  • 32字节的 s s s
  • 1字节的 v v v:其中 v v v为recovery identifier。根据以太坊黄皮书可知, v v v的取值范围为27~30(即0x1b~0x1e)。

参考资料

[1] What is ecrecover in Solidity?
[2] Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT
[3] Ethereum Digital Signatures
[4] ECRecover and Signature Verification in Ethereum
[5] ECDSA Malleability
[6] Precompiled
[7] ECDSA: Elliptic Curve Signatures

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值