以太坊签名涉及的密码学

62 阅读6分钟

本文使用最简单的方式介绍以太坊签名涉及的密码学的核心知识点

签名基本原理

签名的本质就是告诉别人这个事情的确是你做的,但是不用告诉别人所有信息(私钥)

以以太坊转账举例,比如我转给B一个ETH,这时候就会有一条消息m,可以理解为m="我转给B一个ETH",这时候我需要用私钥对m进行签名,得到一个signature,别人拿到m和signature,就能知道这条m的确是你签名的,然后执行m所对应的动作,在这里是给B转一个ETH,这里不需要暴露你的私钥,同时别人又能验证这的确是你要做的事情

要实现这个功能,需要用到密码学的一些知识,主要包括ECCECDSAsecp256k1rsv,本文的目的是用最简单清晰的方式理解这些概念,而不需要去研究清楚其背后复杂的数学公式。

关系梳理

先梳理一下这些概念之间的关系,有个大致的框架,这些概念都是密不可分的

  1. ECC是椭圆曲线密码学,就是说这些特殊的椭圆曲线满足一些数学定律
  2. ECDSA是椭圆曲线数字签名算法,这个算法是基于ECC的,是对ECC的实际应用
  3. secp256k1是一条ECDSA用到的的实际的椭圆曲线
  4. rsv是使用ESDSA(椭圆曲线数字签名算法)得到的签名

ECC(Elliptic Curve Cryptography)

ECC中文名椭圆曲线密码学,其原理是满足这个公式 𝑦2=𝑥3+𝑎𝑥+𝑏的椭圆曲线,这些曲线都是相对于X轴对称的,它上面的点满足一种特定的加法。

image.png

比如说这个曲线上有两个点,P、Q,那么连接P、Q再得到X轴的对称点R,这个R就是P和Q的和,即P+Q=R.不需要理解为啥这样,反正这个椭圆曲线上的点就是满足这个定律,是由背后的数学原理保证的。

ECDSA(Elliptic Curve Digital Signature Algorithm)

ECDSA是椭圆曲线数字签名算法,是基于上面ECC的特性,开发出的一种可以用来对消息签名的算法。

基本原理就是基于上面的ECC加法,那么如果是x个P点自己相加呢,比如xP=X,如果我们知道x,是很容易计算出X的,但是告诉你X,你基本不可能反推出x,因为x是一个很大的数,2的256次方级别的一个数字

然后在椭圆曲线数字签名算法中,就是取x作为私钥,然后X作为公钥,x是256位的二进制的一个数字,X是椭圆曲线上的一个点,用512位二进制表示,XY坐标分别用256位二进制表示

这里还会有一个问题,为什么椭圆曲线上的点都能用整数表示呢,这个也不用管,反正我们只需要知道它用了其它的一些限制,能保证所有点都是能用整数表示的,背后的数学原理不用深究。

公钥私钥

所以我们要生成一个地址,就是用一个随机方法取一个256位长的数字,即上面的x,然后用xP算出X,即为我们的公钥,再对公钥做一下处理,比如取hash,就得到了我们所知道的地址

以太签名的原理就是你要向别人证明你知道x,但是不需要告诉别人x,基于ECC开发出了这样的一套公式可以实现这个功能,即ECDSA

这边直接贴一个图,这个图里的公式不需要全部看懂,感兴趣的可以自己深究一下,看这篇文章

image.png

这里我们只需要知道基于ECC我们知道

n•P + r•P = (n + r)•P

然后对这个公式变换一下可以得到

hash(m, R)•X + R = s•P

其中n·P = X,我们可以把X当成公钥,n当成私钥,即x。

我们只要知道n,就能提供一组m、R、s让hash(m, R)•X + R = s•P这个公式成立,如果不知道n,则无法提供这样一组数据让这个公式成立。

所以这个公式可以用来证明你知道X所对应的x,即私钥。

所以我们取m为要签名的消息,然后R和s就是签名。

secp256k1

这个我们只需要知道这是一条特定的椭圆曲线就行y2=x3+7,ECDSA就是用的这条曲线来进行那些数学计算的

rsv

在以太里的签名就是用rsv表示的,r(32字节、256位),s(32字节、256位),v(1字节,8位),总共65字节。

这里的rsv就是对应于上面公式里的Rs,因为R是一个点,有XY坐标,但是XY分别是256位,完整表示出来太浪费空间了,所以在实际的签名里,只取X轴的坐标,但是同一个X坐标,对应的点有两个点,因为椭圆曲线是相对于X对称的,所以用v来参数来表示取的是哪个点,即这里rv用来表示上面公式里的R

总结

以太坊里的各种交易,底层都是用了上面的ECDSA算法,比如转账交易,这里举个最简单的例子,传给链上的就是类似这样的一个数据结构

{
to: 0x123,
value: 1,
signature: rsv(65字节)
}

其它手续费之类的字段省略了,不影响理解,这个提交说明我要转给0x123这个地址1ETH,然后链上验证signature,验证成功就执行这个操作

在这里to和value都是要签名的消息的原文,我们实际要签名的消息其实是一个hash值,即256位的一个数字,因为签名算法的背后是数学公式,只认数字,这里一般是约定好,你传给我的这些字段用什么方式序列化,然后取hash值,得到要签名的m,签名的地方和验签的地方,用同样的方式序列化就能得到相同的m。

得到m和rsv之后,能反解出X,通过rv能得到R,然后代到公式里看是否满足 hash(m, R)•X + R = s•P,满足则验签通过,执行对应的操作,这里的from地址是X对应的地址,可以根据X计算处理。

这里的P是一个固定的点,是ECDSA提前选好的