以太坊的ecrecover预编译合约
Posted mutourend
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了以太坊的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=\\mathcalO n×G=O, O \\mathcalO 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] k∈R[1,n−1]。(注意,不信任一般的随机数生成器,因为不好的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+r⋅pk)/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 \\mathcalO O,且为其坐标为valid。
- 2)验证公钥 P P P lies on the curve。
- 3)验证公钥 P P P的order为 n n n,即 n × P = O n\\times P=\\mathcalO 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,n−1],s∈[1,n−1]。
- 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)=\\mathcalO (x1,y1)=O,则签名无效。
- 9)若 r ≡ x 1 ( m o d n ) r\\equiv x_1(\\mod n) r≡x1(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
以上是关于以太坊的ecrecover预编译合约的主要内容,如果未能解决你的问题,请参考以下文章
头歌-信息安全技术-用Python实现自己的区块链支持以太坊的云笔记服务器端开发编写并测试用于保存云笔记的智能合约支持以太坊的云笔记小程序开发基础