精通以太坊4:以太坊背后的密码学

精通以太坊4:以太坊背后的密码学

密码学是以太坊的技术基石。

在计算机安全领域有广泛应用

密码学可以用来进行知识证明,在不公开秘密数据的情况下,证明直到秘密的信息(数字签名)

也可以用作证明信息的真实性(数字指纹,也称哈希)

4.1秘钥和地址

有两类以太坊账户可以用来持有和操作以太币:外部账户和合约账户

外部账户对以太币的所有权通过私钥,以太坊地址和数字签名建立起来。

私钥乃是用户与以太坊交互的核心。实际上,用户地址直接由私钥推导出来:

一个私钥会与唯一一个以太坊地址(也称为账户)挂钩

在以太坊系统中没有直接用到私钥,私钥也不会用以太坊网络传输或存储。也就是说,私钥应该保密,既不应该在以太坊网络通信中出现,也不应该存储在链上。只有账户地址和数字签名可以在链上传输或存储

资金的访问与控制权都是通过数字签名实现的,而数字签名也是用私钥生成的。所有以太坊交易都要求在链上包含有效的数字签名。任何持有私钥的人都有对该私钥对应的账户以及账户资金的控制权。如果用户能够安全保管自己的私钥,那么以太坊交易中心的数字签名就能证明资金的实际持有者,因为数字签名能够证明对应私钥的所有权。

在任何以公钥加密为基础的系统(比如以太坊)中,秘钥是成对的,由私钥与公钥组成。我们可以把公钥想象成银行账户,而私钥则是账户密码,前者(公钥,银行账户)用于识别身份,后者(私钥,账户密码)提供对账户的控制权。以太坊用户通常不会直接看到私钥,大部分情况下,私钥以加密形式保存在钱包软件所管理的文件中

在进行以太坊交易的支付过程中,目标收款方式由以太坊地址表示的,与银行转账中用到的收款人账户信息一样。

通常,外部账户的以太坊账户地址由秘钥中的公钥生成,但并不是所有的以太坊账户都代表着一对公钥和私钥,以太坊账户还可以表示合约,合约的背后不需要私钥控制所有权。

4.2公钥密码学和加密货币

公钥密码学(也称为“非对称加密技术”)是现代计算机和信息安全的数学基础。

20世纪70年代,Martin Hellman、Whitfield Diffie和RalphMerkle公开发表了密钥交换协议,这是一次密码学的巨大突破,引发了公众对密码学的强烈兴趣

70年代以前,关于强加密技术的知识由政府控制,公开研究很少

公钥密码学使用一种独特的密钥来保护信息安全。(实现密钥的数学基础是一类具有特殊属性的数学函数,这类函数易于从一个方向进行计算,但是要反向计算却十分困难)。基于这些数学函数,密码学可以用来创造数字密钥和不可篡改的数字签名,而这些密钥与签名的安全性都是由数学定律保障的。

例如:

把两个大质数相乘是一件非常容易的事,但是如果给定两个大质数的乘积,却很难反向推算出构成这个乘积的两个大质数(这被称为质因数分解问题):8018009这个数字,是两个质数的乘积,你找到构成这个乘积的两个质数,要比把这两个质数相乘得到结果困难的多。

在获知一些私密信息的情况下,这类数学函数就可以比较容易地进行反向计算。在上面例子中,直到其中一个质因数是 2003,则很容易得出另一个质因数是4003,这类函数通常被称为陷门函数,因为在获知一部分信息的情况下,你就有捷径得出答案,轻易完成反向计算

另一类十分实用的更高级的数学函数是基于椭圆曲线上的算术运算。

在椭圆曲线运算中,质数的模乘运算是非常简单的,但是模除运算(反向运算)却是几乎不可能的,这被称为离散对数难题,至今我们还没有发现陷门。椭圆曲线密码学在现代计算机系统中被广泛使用,而是以太坊(和其他加密货币)的密钥对和数字签名的基础。

扩展阅读:·

密码学:https://en.wikipedia.org/wiki/Cryptography。

陷门函数:https://en.wikipedia.org/wiki/Trapdoor_function。·

质因数分解:https://en.wikipedia.org/wiki/Integer_factorization。

· 离散对数:https://en.wikipedia.org/wiki/Discrete_logarithm。·

椭圆曲线密码学:https://en.wikipedia.org/wiki/Elliptic-curve_cryptography

在以太坊中,我们使用公钥密码学(也被称为非对称密码学),来创建公钥密钥对。之所以称之为“一对”密钥,是因为公钥是通过私钥生成的。公钥和私钥一起表示一个以太坊账户,公钥用于可访问账户管理(也就是地址)。而私钥用于控制账户内持有的以太币,并控制使用智能合约时所需的认证程序。私钥是生成数字签名所唯一需要的信息,而用户需要数字签名来签署账户内的所有交易以使用账户资金,私钥因此成为控制账户资金的手段。数字签名还用于认证账户所有者与合约用户。

在大多数钱包实现中,私钥和公钥往往作为密钥对一起保存。然而,由于公钥可以直接以私钥计算得出,所以即使只保存了私钥也是没问题的

数字签名可以签署任何消息,对于以太坊交易来说,交易本身的细节就是以消息的形式使用的。密码学(这里指椭圆曲线密码学)中的数学规则使消息(即交易细节)可以与私钥结合在一起,创建出只能用私钥生成的代码。这些代码就是所谓的数字签名。

注意:一笔以太坊交易可以被视为对特定账户的使用请求,以太坊交易可以转移资金或与智能合约交互,在被发送到以太坊网络时,交易必须附带一个与地址对应的私钥创建的签名。椭圆曲线密码学意味着任何人都可以验证交易的有效性,只需要校验数字签名是否与交易细节以及转移资产的地址相匹配。验证过程完全无需使用私钥—私钥完全不必公开。然而,验证过程可以使人们打消疑虑,因为交易只能来自掌握着与以太坊地址对应的私钥的人。这就是公钥密码学的神奇之处。

以太坊协议中并没有任何加密的部分,也就是说,所有以太坊网络上发送的消息都可以(且必须可以)公开阅读,因此,私钥只用来创建数字签名以验证交易

4.3.私钥

私钥是一组随机获取得数字,通过私钥实现的所有权和控制是所有用户控制的根本,这包括该以太坊地址下的以太币的控制,以及针对通过这个地址认证的合约的控制。私钥用来生成数字签名,在交易中心用于证明对以太币的所有权。私钥必须保管好。不能泄露,不能丢失,丢失无法找回,

4.4通过随机数生成私钥

生成私钥的第一步,也是最重要的一步就是找到一个密码学安全的熵,或者称为随机源。

生成以太坊私钥基本就是在 1–2^256之间的选择数字。只要选择的过程不可预测不可重复,那么通过什么方式获得这个数字并不重要。

以太坊软件使用底层操作系统的随机数生成器生成一个256位的“熵”,操作系统的随机数生成器通常以用户的一些随机行为为基础,因此,在生成随机数的过程中。系统可能要求以用户随意滑动鼠标,或者在键盘上随意敲几个键。另一种替代性方案是收集计算机麦克风通道中的噪声。

更准确的说,以太坊私钥可以是任何比2256略微小一点的正整数,2256是一个77位的十进制数字,接近于1.158X10^77. 私钥的数字与2^256的前38位相同,这被定义为以太坊椭圆曲线的阶。

要生成私钥,我们随机取出一个256比特的数字,然后检查他是否在有效范围内。

用编程的术语说,其实现方式是:将一个(从密码学意义上上安全的熵源中得出的)很大的随机字符串放入256比特的哈希算法中,比如Keccak-256或者SHA256,这两种算法会便捷的产生一个256比特的数字。如果这个结果在有效的范围内,我们就有了合适的私钥。否则,我们就要用另一个随机数字再试一次

以太坊私钥数字区间大小为2256,这是一个大道无法言喻的数字,这个数字在十进制中几乎是1077,也就是说,是个77位数,我们对比一下,在可见的宇宙中,人们总共有10^80个原子,因此我们几乎有足够的私钥给宇宙中的每一个原子。当你随机的选择了一个私钥后,几乎不可能会有另一个人猜到,或者选中同一个

需要注意的是,私钥生成过程是离线的,不需要与以太坊网络有任何交互,甚至不需要与任何人有交互。要想选到一个无人会选的私钥,就需要生成真正的随机数。如果你自己选择一个数字,这样其他人也尝试这个数字(并花光你的以太币)的概率会大很多。使用非真随机数生成器是个更差的注意,因为这种假随机更明显且容易重复。就像是在线账户里用到的密码,私钥也需要无法被猜到,幸运的是,你并不需要记得私钥,所以可以用最好的方法来选择私钥----真随机数

不要尝试自己编程来创建随机数,或者使用那些编程语言类库中自带的简易随机数生成器,使用密码学安全的伪随机数生成器(如CSPRANG),并且使用熵源充足的随机源做种子

下面是一个随机生成的私钥,以十六进制的格式显示(256个二进制位,显示为64个十六进制数,每个代表4比特)

fjhhjhhkjhjhjkhkhkjhljhlkhyy29863t8xbs07qucy9 3u97cn 12uyyhc556dcrycfd

4.5公钥

每个以太坊公钥都是椭圆曲线上的一个点,也就是说,每个公钥都是一组x,y坐标,这个坐标正好满足椭圆曲线的方程

简单的说,以太坊的公钥由两个数字组合在一起,这两个数字由私钥经过单向计算得来。这意味着通过私钥计算获得公钥是非常容易的,但是你不能反过来,通过公钥算出它所对应的私钥。

公钥是通过私钥使用椭圆曲线的乘法运算得来的,而这个乘法运算基本上是不可逆的:

K=K*G,其中k是私钥,G是一个常量点,称为生成点,K是计算得来的公钥,

*是椭圆曲线函数的乘法运算符号。

这与普通乘法运算的规则是不同的,除了与普通乘法有相同的功能属性,其他都不一样。

举个例子;反向运算(普通乘法的反向运算就是除法),也被称为获取“离散对数的计算,即在已知K的情况下求解K,是非常困难的,必须采用暴力穷举的方式尝试所有可能的K

也就是说,椭圆曲线上的算术运算跟常规的数学运算是不一样的,一个点(G)可以与一个整数(k)相乘来获得另外一个点(K).但是椭圆曲线的世界里没有除法的概念。因此不可能简单的通过计算公钥K对G点的除法来计算私钥。

椭圆曲线乘法就是我们密码学中提到的“单向函数”:它很容易从一个方向(乘法)进行计算,但是不可能采用反向(除法)的方式计算。私钥的持有者很容易算出公钥,然后把公钥公开,因为他确信没有人可以通过这个公钥反向推算出私钥。这个神奇的数学算法造就了不可篡改和安全的数字签名,用来

证明以太币的所有权,以及对合约进行控制

4.6椭圆曲线密码学的基本概念

椭圆曲线密码学是基于离散对数问题的非对称密码学(也被称为公钥密码学)

他是基于椭圆曲线上点位的加法和乘法的不可逆特性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vFTAiUYK-1585387103276)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1582982780939.png)]

以太币使用跟比特币系统相同的椭圆曲线算法,称为secp256k1.这样以太坊就可以直接使用比特币系统中大量的椭圆曲线函数库相关的开发工具。

以太坊使用一条特定的椭圆曲线和一组数学常量,这是一个被称为secp256k1的标准,由NIST设定。

secp256k1曲线由下列函数定义,这些函数生成了椭圆曲线:

y2=(x^3+7)over(F p)

或·

y^2 mod p=(x^3+7)mod p

mod p (素数的模)表示曲线位于素数阶p的有限域中,这也可以表示为p,其中的p=2256-232-29-28-27-26-2^4-1是一个非常大的素数。

曲线的定义位于素数阶p的有限域中,而不是我们常见的实数空间。

这个曲线的模式就像是散布在两个维度上的一组点,这是很难图形化表示的。然而,对于位于实数域的椭圆曲线,对应的算法也是一样的。

例如,图4-2展示了同样一个位于有限域的椭圆曲线,但是它的素数阶(17)要小得多,显示为一个网格中的一系列点。椭圆曲线使用的secp256k1可以被认为是比这个复杂得多的模式,散布在一个巨大无比的网格之中。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MFhCgrar-1585387103278)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1582983601838.png)]

例如:下面的Q点对应的(x,y)坐标是secp256k1曲线上的一个点位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q5TgTwD7-1585387103278)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1582983695818.png)]

代码4-1演示了如何使用python来检验这个点是否位于椭圆曲线上

变量x和y是 Q点坐标,变量p是椭圆曲线的素数阶(这个素数是用来进行所有的求模计算)

python代码的最后一行是椭圆曲线的等式(%运算符在python中代表求模运算)。如果x和y的确实椭圆曲线上的点,那么它们就会满足方程,并且运算的结果是零(OL是一个零值长整数).你可以自己编程尝试,通过Python的IDE,把下面的代码复制到>>>提示符之后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JHEuPl8h-1585387103280)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1582984988721.png)]

4.7椭圆曲线上的运算

椭圆曲线上的很多数学运算看上去跟我们在学校学习的整数世界的数学运算相似。特别是,我们可以定义一个加法运算符,并不是做数字之间的加法,而是把曲线上的两个点相加。有了加法运算符以后,我们还可以定义乘法运算符,用来在一个点和一个整数之间进行乘法运算,类似于重复进行加法运算。

椭圆曲线上加法运算的定义就是给定椭圆曲线上的两个点p1和p2,椭圆曲线上存在第三个点,满足P3=P1+P2

从几何学的意义上来说,第三个点的计算其实是P1和P2之间画一一条线。这条线会与椭圆曲线存在唯一的相交点(超神奇),这个点称为P3’=(x,y),对应着在x轴我们就可以得到P3=(x,-y)

如果P1和·p2是同一点,那么p1和·p2之间的这条线就应该是椭圆曲线P1(P2)点的切线。

这条切线会跟椭圆曲线存在唯一的相交点。你可以通过微积分的方式来确定这条切线上的斜率。这样的计算真的可以产出结果,即使我们只有曲线上的两个坐标,仍旧可以算出对应的切线斜率

在椭圆曲线的数学运算中,存在一个“无限远点”,这个点类似常规数学中的零。在计算机中,它有时被表述为x=y=0(这并不满足椭圆曲线的方程,但这时一个很容易验证的例子)。有一些特殊的案例可以用来解释为什么我们需要这个无限远点。

在一些情况下(比如P1和P2有相同的x值,却有不同的y值),那么两点的连线就是一条垂直的直线,这样的情况下,p3就是无限远点

如果p1是无限远点,那么 p1+p2=p2.如果,p2是无限远点,那么 p1+p2=p1.这个例子展示了“无限远点’'怎么扮演着数学中零的作用

这意味着,加法是满足结合律的,也就是说(A+B)+C=A+(B+C),这意味着我们可以直接写A+B+C,即使不用圆括号,也不会产生运算上的歧义

我么已经定义了加法,现在可以借此延伸出乘法的定义,对于椭圆曲线上的p点,如果k是一个整数,那么k*p=p+p+p…+p(相加k次)。注意,有时候k会被称为“指数”,这比较容易混淆

4.8生成公钥

我们从随机得来的私钥K开始,使用椭圆曲线上预先定义好的名为生成点的G点来产生另一个位于椭圆曲线上的点,这就是对应的公钥K

K=K*G

生成点由secp256k1椭圆曲线标准定义,在所有的secp256k1实现中,这个点保持不变,所有从这个曲线产生的公钥都是经过相同的生成点计算而来的。因为对于所有的以太坊用户而言,生成点始终保持不变,所以使用一个私钥K与生成点G计算之后,总是会得出相同的公钥K。K和K之间的关系是固定的,但是只能从一个方向进行计算,也就是通过k计算出K,这也是为什么一个以太坊地址(从公钥k而来)可以被公开分享,而不用担心对应的私钥(K)可能会被人反向算出

如同我们在上一节中提到,K*G的乘法运算相当于是重复多次的加法运算,也就是G+G+G+…+G,重复K次,概括而言,为了从私钥k计算出公钥k,我们需要把生成点G反复相加K次

通过私钥可以推算出公钥,但是通过公钥无法反向计算得出私钥,因为这个数学算法是单向的

现在,让我们把这项计算用在之前“私钥”一节中生成的那个私钥,并通过这个私钥来计算得出公钥

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ffwO9kyh-1585387103281)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583546584434.png)]

一些密码学类库可以帮助我们使用椭圆曲线加法来计算K,计算得出的公钥K定义为一个点:

K=(X,Y)

其中:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rvHWUV4R-1585387103282)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583546737418.png)]

在以太坊协议中,你可能会看到采用130个十六进制字符(65字节)表示的公钥。这是由SECG所发布的行业标准的一种序列化编码方式,在高效密码学标准(SECI)中有文献记载

http://www.secg.org/sec1-v2.pdf

这个标准定义了四种可能的前缀,用来表示椭圆曲线上的点位

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vXQKGaCg-1585387103282)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583546963308.png)]

以太坊只使用未压缩的公钥,因此唯一相关的前缀就是0x04,包括x和y坐标的公钥经过编码后的形态如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9TaQ8ZMB-1585387103283)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583547201102.png)]

因此,我们在上文计算得出的公钥,经过编码后的形态为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FbBYbGCM-1585387103284)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583547240155.png)]

4.9椭圆曲线程序库

数字货币领域使用了 secp256k1标准的椭圆曲线的多个程序实现:

OpenSSL(https://www.openssl.org/)

​ OpenSSL程序库提供了非常丰富的密码学基础类库,包括完整的secp256k1,例如,我们可以使用EC_POINT_mul来获得公钥

libsecp256k1(https://github.com/bitcoin-core/secp256k1)

​ 比特币核心使用的是Libsecp256k1,这是由c语言实现的secp256k1椭圆曲线和其他相关的密码学类库,该算法是从零开发的,旨在替代OpenSSL,相比OpenSSL,其在性能和安全性方面都更胜一筹

4.10密码学哈希函数

以太坊中,密码学哈希函数无处不在,实际上,哈希函数在所有的加密货币中广泛应用。

密码学家Bruce Schneier(http://bit.ly/2Q79qZp),说:相比加密算法,单向哈希函数在现代密码学中才是主力军

在这一节,我们将讨论哈希函数,探索其基本特性,并理解为何这些特性可以让哈希函数在现代密码学领域变得如此重要。我们在这里着重讨论哈希函数,是因为以太坊公钥到地址转换过程中用到了哈希函数。哈希函数还可以用于创建数字指纹,帮助数据验证。简单地说,哈希函数(http://bit.ly/2CR26gD)是一个可以将任意长度数据映射成固定长度数据的数学函数。哈希函数的输入称为预映射,消息,或就叫输入数据,哈希函数的输出数据被称为哈希。密码学哈希函数(http://bit.ly/2Jrn3jM)是哈希函数中的一个特殊类别,具有特别的属性,可以很好的保护平台(以太坊)的安全

加密哈希函数是一种单向的哈希函数,可以将任意长度的数据映射成固定长度的比特序列。这种“单向性”意味着,如果我们只知道哈希函数的输出值,还原出输入数据在计算上是不可能的。要发现可能的输入值,唯一的方式就是暴力搜寻,检查每一个可能的输入是否能得到同样的输出值,给定无限的搜索空间,显然,求得原输入在实践中是不可能的。即便可以找到一些输入能产生同样的哈希值,也不一定就是我们想求的那个初始输入:因为哈希函数是“多对一”的函数,哈希函数的性质越好,哈希碰撞的情形越少。对以太坊来说,这基本不可能。

让我们来认识一下密码哈希函数的五个主要特性:

确定性

​ 同样的输入信息总是会产生相同的输出哈希

可验证性

​ 计算任意输入信息量的哈希运算非常高效(线性的计算性能)

无关联性

​ 对于输入信息的微小改变(哪怕只改变一个比特)都会对输出结果的哈希造成巨大的变化,而且这样的变化与之前的消息之间没有任何关联性

不可逆性

​ 从哈希反向计算得出输入的原始信息是不现实的,只能通过暴力穷举式的尝试

碰撞保护性

​ 几乎不可能找到能够得到同一个哈希输出的两个不同信息。这里的碰撞保护性对于防止伪造以太坊中的数字签名尤其重要。这些属性的结合使得密码哈希函数在安全领域有着广泛的应用:

》数据指纹

》数据一致性(错误侦测)

》工作量证明

》身份认证(密码哈希和密钥延伸)

》伪随机数生成器

》消息承诺(commit-reveal机制)

》唯一标识符

随着对以太坊的深入研究,我们会在系统中发现很多上述应用

4.11以太坊中的密码学哈希函数:Keccak-256

以太坊协议中多处用到了名为Keccak-256的密码学哈希函数,Keccak-256是07年由NIST在SHA-3密码学哈希函数竞赛中提出的,Keccak胜出并最终在 2015年成为 FIPS 202标准

然而在以太坊的开发过程中,NIST标准并没有完全确定,在标准化过程完成后,NIST调整了Keccak中的一些参数,意在提升它的性能。与此同时,Edward Snowden披露的政府文档中揭示,NIST可能受到美国国家安全部门的影响,有意的弱化了Dual_EC_DRBG随机数生成器标准,在这个随机数生成器后加入了后门。这导致了公众对变更提案的强烈抵制,并极大地延缓了对应的SHA-3标准化进程。因此,以太坊基金会决定实现由发明者提出的最原始的Keccak算法,而不是在以太坊中使用经过NIST修改的SHA-3标准

你会在以太坊的代码和文档中看到大量"SHA-3"的字样,这些多数都是指原始版本的Keccak-256,而不是经过SHA-3标准化的FIPS-202.这两者在实现层的差别微乎其微,只是填入参数的区别,但是对于给定的输入内容,Keccak-256所产出的哈希肯定与FIPS-202 SHA-3所产出的哈希完全不同

4.12我在使用哪一个哈希函数?

两个哈希都叫"SHA 3",我们如何辨别所使用的程序库是FIPS-202 SHA-3 还是Keccak-256?

最简单的办法就是采用测试矢量,用一个给定输入的已知结果来判断。用于测试哈希函数是最通用的方法是使用空的输入。如果使用哈希函数计算输入的空白字符串的哈希值,应该得出以下结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fVKmD4k6-1585387103286)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583549917234.png)]

因此别管这个函数叫什么名字,我们都可以通过简单的测试来确定它到底是原始的Keccak-256实现,还是NIST最终标准化的FIP-202 SHA-3实现。记住,尽管在代码中有些地方采用了SHA-3的命名,以太坊使用的是 Keccak-256实现

由于以太坊使用的哈希函数(Keccak-256)与最终标准化的哈希函数(FIPS -202 SHA-3)命名造成了一些混轮,我们正想办法将所有实现代码,操作码,类库里的SHA3重新命名为Keccak256.

详见ERC59(https://github.com/ethereum/EIPs/issues/59)

接着,我们来检验一下Keccak-256在以太坊中的第一个应用:从公钥生成以太坊地址。

4.13以太坊地址

以太坊地址是唯一标识符,从公钥或者合约通过单向哈希函数Keccak-256计算而来。

在之前的例子中,我们从私钥开始,通过椭圆曲线乘法运算获得了一个公钥。

私钥k:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hvh2YCzk-1585387103287)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583550617315.png)]

公钥K(x和y坐标组合后以十六进制的方式显示)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOdgTrxk-1585387103288)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583550717714.png)]

在进行以太坊地址运算时,公钥的前缀必须是十六进制的04

我们使用Keccak-256来计算公钥的哈希值

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzL6Qy5c-1585387103289)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583550817686.png)]

然后只保留后20位(大端序中最末的字节),这就是我们的以太坊地址:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vAolVh5d-1585387103290)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583550905908.png)]

很多情况下,你会看到以太坊地址带有 0X的前缀,这表示它采用十六进制的表示方式

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-siZlkID3-1585387103291)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583550964056.png)]

4.14以太坊地址格式

以太坊地址是十六进制的数字,来自于公钥经过Keccak-256哈希运算之后得出结果的后20位

不同于比特币,比特币地址中包含了一个内置得校验器用于防止可能的错误地址输入。以太坊的地址是原生的十六进制数据,没有任何校验信息

这个决定背后的原因在于,以太坊地址通常都隐藏在类似域名服务等高层抽象之后,如果需要,对应的校验也应该在抽象层之上实现

然而,由于抽象层的开发十分缓慢,这样的设计决策也导致了一些问题,比如:在网络生态早期,由于输入错误地址导致的一些以太币丢失。以太坊域名服务的开发进度较预期更慢,而钱包的其他编码标准也并没有在开发者中的得到广泛应用

4.15 ICAP协议

互换客户端地址协议(ICAP)是一种与国际银行账户(IBAN)编码部分兼容的以太坊地址编码形式,为以太坊地址提供通用,经校验且可互操作的编码

ICAP地址可以用于编码以太坊地址,也可以用于编码注册在以太坊域名注册服务之下的通用名称。关于ICAP的更多内容,可以在 Ethreum Wiki(http://bit.ly/2JsZHKu)上看到

IBAN是一个国际通用的用于识别银行账户的编码体系,通常用于电汇转账,在欧元区等地域广泛使用。IBAN是一个中心化的,受到高度监管的服务。ICAP是一个去中心化的实现,但仍与以太坊地址相兼容

IBAN是一个包括34个数字字符(不区分大小写)的字符串,含有国家代码,校验码和每个国家内的银行识别码

ICAP使用了与IBAN相同的结构,以代表以太坊的非标准国家代码“XE"开头,后接两位校验码与三个可能的账户标识符变量:

直接式:

最多包含30个字符的大端序base-36编码,代表以太坊地址的末155比特。因为该编码方式无法包含通用以太坊地址的全部160比特,所以只能用于由一个或者多个零字节起始的以太坊地址。

其优势在于与IBAN的字段长度和校验码格式兼容,

例如:XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD(33字符)

基础式:

与直接式类似的编码方式,唯一区别是有31个字符。该方式可以编码任何以太坊地址,但结果是这样的编码与IBAN字段的验证不兼容。例如:

XE18CHDJBPLTBCJ03FE9 O2NS0BPOJVQCU2P(35字符)

非直接式:

在编码中加入一个可以通过以太坊域名注册服务解析出以太坊地址的标识符。非直接式使用16位字符,包含一个资产识别符(ETH),一个域名(XREG)和9个字符的人类可读的名字(如:KITTYCATS).

例如:

XE##ETHXREGKITTYCATS(20字符), ##是两个经过计算得出的校验字符。

我们可以使用 helpeth命令行工具创建ICAP地址,现在我们使用之前获得的那个私钥试验一下(给私钥添加0x前缀,然后将其作为helpeth命令的参数)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2DvDsIoW-1585387103292)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583553282068.png)]

在提供ICAP地址的同时,helpeth命令也构建了一个十六进制的以太坊地址

在我们这个例子中生成得ICAP地址是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FbIjQB4S-1585387103293)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583553344767.png)]

因为我们的以太坊地址恰巧是从零开始的,所以可以使用 ICAP编码方法中的“直接式”获得一个兼容IBAN格式的地址。可以看出它们是兼容的,因为这个ICAP地址的长度为 33字符

如果你的以太坊地址不是从零开始的,那么只能通过“基础式”编码,生成的地址是35字符长,与IBAN格式不兼容

获得从零开始的以太坊地址的概率是1/256.为了生成这样一个地址,需要平均对256个不同的私钥进行运算,才能获得一个能够产生IBAN兼容格式的公钥地址

目前阶段,只有少量的钱包支持 ICAP地址格式

4.16 EIP-55:十六进制编码地址的大写校验

由于ICAP和域名服务推进的速度缓慢,有人提出了一个新的编码标准方案(EIP-55)\

https://github.com/Ethereum/EIPs/blob/master/EIPS/eip-55.md

EIP-55为以太坊地址提供了一种向后兼容的校验机制,这个机制是通过修改十六进制地址中的大小写字母来实现的。以太坊地址并不区分大小写,对于钱包软件来说,不论是包含大写字母还是小写字母格式的地址都是一样的。

通过修改地址中字母的大小写,我们可以获得一种校验,用于保护地址的完整性,避免地址输入式的人为错误。不支持EIP-55的钱包软件只需要忽略这些地址中存在的大小写组合方式。那些支持EIP-55的钱包软件,可以通过这些大小写来验证地址的正确性,错误检出率高达99.986%

混合大小写编码方式的改动非常微秒,你在最初可能无法注意到其中的变化

我们的示例地址是:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XH1IiPYe-1585387103294)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583554798889.png)]

通过EIP-55混合大小写编码后,地址变为:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LnDz65c-1585387103295)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583554835820.png)]

你能看出其中的区别吗?十六进制中的字符(A-F)有一部分已经变成大写了,有些却依旧保持小写

EIP-55的实现非常简单,我们对全小写的十六进制地址计算Keccak-256哈希。这个哈希被视为地址的数字指纹,为我们提供了一个方便的校验方式。任何地址中的微小变化,都会在对应的哈希中带来巨大的变化。这样我们就能发现可能存在的输入或者打字错误。接着,把这个哈希校验信息通过1大写修改的方式融合到地址中。我们一步步来看看是如何实现的。

1.针对全小写的地址计算一次哈希,不包括0x前缀。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GBClPG91-1585387103295)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555123026.png)]

2.注意检查地址中的字母,

如果在哈希中对应的十六进制大于或者等于8,就把这个字母改为大写。如果我们把地址和其他的十六进制哈希值并列在一起,就很容易看出端倪

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lQuXbnZE-1585387103296)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555295095.png)]

在我们地址中,第四位有一个小写的d,哈希中对应位数的数值是6,因为它小于8,所以保持d的小写格式不变。地址中下一个字母是f,位于第六位。哈希值中对应的位置的数字是c,它比8要大,因此我们把地址中的f改为大写的F。以此类推。如你所见,我们只使用了哈希值中的前20字节(40个十六进制字符)作为校验,因为地址中只有20个字节

检查地址中剩余的字符,看看你是否可以判断哪一个字母应该改为大写,它对应在哈希中的内容是什么?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iW2a6GbK-1585387103297)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555591876.png)]

用EIP-55编码方式检测错误

现在,我们来看看EIP-55格式的地址如何帮助我们发现错误,假设我们打印出了一个以太坊地址,是用 EIP-55格式编码的:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fIYWTFgX-1585387103298)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555677539.png)]

幸运的是,我们的钱包兼容EIP-55格式。它注意到了地址中混合的大小写字母,并且会尝试验证这个地址是否正确。钱包会把地址改为全小写,然后计算它的哈希

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bq0MXWEb-1585387103299)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555757055.png)]

如你所见,尽管地址只有一个字母出错了(而且e和f之间其实只有一个比特的差异而已),但这个地址的哈希发生了彻底的变化。这就是哈希函数带来的功能,可以用来生成非常有效的校验数据

现在,我们把地址和它的哈希对齐,来检查大小写是否满足检验:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rRMaGaFd-1585387103300)(C:\Users\xiaoweifeng\AppData\Roaming\Typora\typora-user-images\1583555891665.png)]

全都乱套了。有几个字母被错误地设定成了大写、。现在,记住,大写的位置应该跟哈希校验的值匹配对应。

用EIP-55编码方式检测错误

现在,我们来看看EIP-55格式的地址如何帮助我们发现错误,假设我们打印出了一个以太坊地址,是用 EIP-55格式编码的:

[外链图片转存中…(img-fIYWTFgX-1585387103298)]

幸运的是,我们的钱包兼容EIP-55格式。它注意到了地址中混合的大小写字母,并且会尝试验证这个地址是否正确。钱包会把地址改为全小写,然后计算它的哈希

[外链图片转存中…(img-bq0MXWEb-1585387103299)]

如你所见,尽管地址只有一个字母出错了(而且e和f之间其实只有一个比特的差异而已),但这个地址的哈希发生了彻底的变化。这就是哈希函数带来的功能,可以用来生成非常有效的校验数据

现在,我们把地址和它的哈希对齐,来检查大小写是否满足检验:

[外链图片转存中…(img-rRMaGaFd-1585387103300)]

全都乱套了。有几个字母被错误地设定成了大写、。现在,记住,大写的位置应该跟哈希校验的值匹配对应。

我们输入的地址中的大小写并不满足刚才计算得出的结果,这就意味着地址发生了变化,输入过程中发生了错误。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值