以太坊的基础技术之一是密码学,这是数学的一个分支,广泛用于计算机安全。密码学在希腊语中意为“秘密写作”,但密码学的科学不仅包括秘密写作,也称为加密。密码学也可用于证明秘密知识而不泄露秘密(数字签名),或证明数据的真实性(数字指纹)。这些类型的加密证明是对以太坊和大多数区块链系统至关重要的数学工具,广泛用于以太坊应用程序。具有讽刺意味的是,加密并不是以太坊的重要组成部分,因为它的通信和交易数据没有加密,也不需要加密来保护系统。在本章中,我们将介绍以太坊中用于控制资金所有权的一些密码学技术。
介绍
以太坊有两种不同类型的账户,可以拥有和控制以太:外部账户(EOA)和合约。在本节中,我们将研究密码学的使用,以通过外部拥有的帐户(即私钥)建立以太的所有权。
EOA中以太的所有权是通过数字密钥,以太坊地址和数字签名建立的。数字密钥实际上不存储在区块链中或不在以太坊网络上传输,而是由用户在文件或称为钱包的简单数据库中创建和存储。用户钱包中的数字密钥完全独立于以太坊协议,并且可以由用户的钱包软件生成和管理,而无需参考区块链或访问互联网。数字密钥可以实现以太坊的许多有趣属性,包括去中心化的信任和控制以及所有权证明。
以太坊交易要求有效的数字签名包含在区块链中,只能用密钥生成; 因此,任何拥有该密钥副本的人都可以控制以太。以太坊交易中的数字签名证明了资金的真正所有者。
数字密钥成对出现,包括私有(秘密)密钥和公钥。可以将公钥视为与银行帐号相似,私钥与密码PIN类似,可提供对帐户的控制。这些数字密钥很少被以太坊的用户看到。在大多数情况下,它们存储在钱包文件中并由以太坊钱包软件管理。
在以太坊交易的支付部分中,预期接收者由以太坊地址表示,该地址以与支票上的受益人姓名相同的方式使用(即,“支付给订单”)。在大多数情况下,以太坊地址是从公钥生成的并且对应于公钥。但是,并非所有以太坊地址都代表公钥; 他们也可以代表合约,我们将在[合约]中看到。以太坊地址是用户经常看到的密钥的唯一表示,因为这是他们需要与世界共享的部分。
首先,我们将介绍密码学并解释以太坊中使用的数学。接下来,我们将了解如何生成、存储和管理密钥。最后,我们将回顾用于表示私钥和公钥以及地址的各种编码格式。
公钥加密和加密货币
公钥加密是现代信息安全的核心概念。1970年代由Martin Hellman,Whitfield Diffie和Ralph Merkle首次公开发明,这是一个巨大的突破,引发了第一次公众关注的密码学领域。在70年代之前,强大的密码学知识在政府的控制下进行,几乎没有公共研究,直到公开密钥学研究的公开发表。
公钥加密使用用于保护信息的唯一密钥。这些唯一密钥基于具有独特属性的数学函数:它们易于在一个方向上计算,但很难在反方向上计算。基于这些数学函数,密码学能够创建数字密钥和不可伪造的数字签名,这些签名受到数学定律的保护。
例如,将两个大质数相乘是微不足道的。但考虑到两个大素数的乘积,很难找到素因子(一个称为素数因子分解的问题)。假设我出现了数字6895601,并告诉你它是两个素数的乘积。找到这两个素数要比将它们乘以产生6895601要困难得多。
如果你知道一些秘密信息,这些数学函数中的一些可以很容易地反转。在上面的例子中,如果我告诉你其中一个主要因素是1931,你可以通过简单的除法轻松找到另一个:6895601/1931 = 3571.这些函数被称为trapdoor函数,因为给出了一条秘密信息,你可以采取一种快捷方式,使得反转功能变得微不足道。
在密码学中有用的另一类数学函数基于椭圆曲线上的算术运算。在椭圆曲线算术中,乘以modulo的素数很简单,但除法是不可能的(称为离散对数问题)。椭圆曲线密码术广泛用于现代计算机系统中,是以太坊(和其他加密货币)数字密钥和数字签名的基础。
阅读有关密码学和现代密码学中使用的数学函数的更多信息:
- 密码学:https://en.wikipedia.org/wiki/Cryptography
- Trapdoor函数:https://en.wikipedia.org/wiki/Trapdoor_function
- Prime Factorization:https://en.wikipedia.org/wiki/Integer_factorization
- 离散对数:https://en.wikipedia.org/wiki/Discrete_logarithm
- 椭圆曲线密码学:https://en.wikipedia.org/wiki/Elliptic_curve_cryptography
在以太坊中,我们使用公钥加密来创建一个控制ether访问并允许我们对合约进行身份验证的密钥对。密钥对由私钥、唯一公钥组成,并且被认为是“pair”,因为公钥是从私钥导出的。公钥用于接收资金,私钥用于创建数字签名以签署交易来花费资金。数字签名也用于验证合约的所有者或用户,我们将在[contract_authentication]中看到。
公钥和私钥之间存在数学关系,允许私钥用于在消息上生成签名。可以在不泄露私钥的情况下针对公钥验证此签名。
在花费以太时,当前所有者在交易中呈现她的公钥和签名(每次不同,但是从同一私钥创建)。通过公钥和签名的呈现,以太坊系统中的每个人都可以独立有效地验证和接受交易,确认交易以太的人在转移时拥有它们。
Tip | 在大多数钱包实现中,为方便起见,私钥和公钥一起存储为密钥对。但是,可以从私钥简单地计算公钥,因此也可以仅存储私钥。 |
---|
为什么使用非对称加密技术(公钥/私钥)?
为什么以太坊使用非对称加密?它不习惯“加密”(秘密)交易。相反,非对称加密的有用特性是生成数字签名的能力。可以将私钥应用于交易的数字指纹以产生数字签名。此签名只能由具有私钥的人员生成。但是,任何有权访问公钥和交易指纹的人都可以使用它们来验证签名。非对称加密的这种有用属性使任何人都可以验证每个交易上的每个签名,同时确保只有私钥的所有者才能生成有效的签名。
私钥
私钥只是一个随机挑选的数字。对私钥的所有权和控制权是用户控制与相应的以太坊地址相关联的所有资金的根源,以及对授权该地址的合约的访问权。私钥用于通过证明交易中使用的资金所有权来创建需要花费以太的签名。私钥必须始终保密,因为向第三方披露私钥等同于让他们控制以太和由该密钥保护的合约。还必须备份私钥并防止意外丢失。如果它丢失了,它就无法恢复,而它所保证的资金也会永远丢失。
Tip | 以太坊私钥只是一个数字。您可以使用硬币、铅笔和纸张随机选择您的私钥:掷硬币256次,您可以在以太坊钱包中使用随机私钥的二进制数字。然后可以从私钥生成公钥和地址。 |
---|
从随机数生成私钥
生成密钥的第一步也是最重要的一步是找到安全的熵源或随机性。创建以太坊私钥与“选择1到之间的数字”基本相同。用于选择该数字的确切方法无关紧要,只要它不可预测或不可重复即可。以太坊软件使用底层操作系统的随机数生成器产生256位熵(随机性)。通常,OS随机数生成器由人类随机源初始化,这就是为什么可能会要求您将鼠标摆动几秒钟,或者按键盘上的随机键。
更准确地说,可能的私钥范围略小于。私钥可以是1到n-1之间的任何数字,其中n是常数(n = 1.158*,略小于),定义为以太坊中使用的椭圆曲线的顺序(参见[椭圆曲线加密解释])。为了创建这样一个密钥,我们随机选择一个256位的数字并检查它是否小于n-1.在编程术语中,这通常是通过从密码安全的随机源收集的更大的随机bits来实现的。转换为256位哈希算法,如Keccak-256或SHA256(参见[cryptographic_hash_algorithm]),这将方便地产生256位数字。如果结果小于n - 1,我们有一个合适的私钥。否则,我们只需再次尝试获取另一个随机数。
Warning | 不要编写自己的代码来创建随机数或使用编程语言提供的“简单”随机数生成器。使用加密安全的伪随机数生成器(CSPRNG)和来自足够熵源的种子。研究您选择的随机数生成器库的文档,以确保它是加密安全的。正确实施CSPRNG对密钥的安全性至关重要。 |
---|
以下是以十六进制格式显示的随机生成的私钥(k)(256位显示为64个十六进制数字,每个4位):
f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
Tip | 以太坊私钥空间的大小()是一个不可思议的大数字。十进制约为。为了比较,可见宇宙估计包含个原子。 |
---|
公钥
以太坊公钥是椭圆曲线上的一个点,这意味着它是一组满足椭圆曲线方程的X和Y坐标。
简单来说,以太坊公钥是两个连接在一起的数字。这些数字是通过只能单向计算的私钥生成的。这意味着如果您拥有私钥,那么计算公钥是微不足道的。但是您无法从公钥计算私钥。
MATH即将发生!不要惊慌。如果您发现很难阅读上一段,则可以跳过接下来的几节。有许多工具和库可供您进行数学计算。
使用椭圆曲线乘法从私钥计算公钥,这是不可逆的:K = k * G,其中k是私钥,G是称为生成点的常数点,K是结果公钥。反向操作,称为“找到离散对数” - 计算k,如果你知道K - 就像尝试所有可能的k值一样困难,即暴力搜索。
简而言之:椭圆曲线上的算术不同于“常规”整数算术。点(G)可以乘以整数(k)以产生另一个点(K)。但是没有除法之类的东西,因此不可能简单地将公钥K“除”点G来计算私钥k。这是公钥加密和加密货币中描述的单向数学函数。
Tip | 椭圆曲线乘法是密码学家称之为“单向”函数的一种函数:它很容易在一个方向上进行(乘法)而在反向(分割)中是不可能的。私钥的所有者可以轻松地创建公钥,然后与世界共享它,知道没有人可以反转该功能并从公钥计算私钥。这种数学技巧成为不可伪造和安全的数字签名的基础,证明了以太坊资金的所有权和合约的控制权。 |
---|
在我们演示如何从私钥生成公钥之前,让我们更详细地看一下椭圆曲线加密。
椭圆曲线加密解释
椭圆曲线加密是一种基于离散对数问题的非对称或公钥加密,如椭圆曲线的点上的加法和乘法所表示的。
椭圆曲线的可视化是椭圆曲线的一个例子,类似于以太坊使用的曲线。
Tip | 以太坊使用与比特币完全相同的椭圆曲线,称为secp256k1。这使得重用比特币的许多椭圆曲线库和工具成为可能。 |
---|
图1.椭圆曲线的可视化
以太坊使用特定的椭圆曲线和一组数学常数,如由国家标准与技术研究所(NIST)建立的名为secp256k1的标准中所定义。secp256k1曲线由以下函数定义,该函数生成椭圆曲线:
或者
所述mod p(mod 素数p)表明,该曲线是在素数阶的有限域p,也写为,其中,一个非常大的素数。
因为此曲线是在素数阶的有限域而不是实数上定义的,所以它看起来像是在两个维度上散布的点图案,这使得难以可视化。但是,数学与实数上的椭圆曲线相同。例如,椭圆曲线密码学:在F(p)上可视化椭圆曲线,p = 17,在素数阶17的小得多的有限域上显示相同的椭圆曲线,显示网格上的点图案。secp256k1以太坊椭圆曲线可以被认为是在一个不可思议的大网格上更复杂的点图案。
图2.椭圆曲线加密:在F(p)上可视化椭圆曲线,p = 17
因此,例如,以下是坐标(x,y)的点Q,它是secp256k1曲线上的一个点:
Q =(49790390825249384486033144355916864607616083520101638681403973749255924539515,59574132161899900045862086493921015780032175291755807399284007721050341297360)
[使用Python确认这一点在椭圆曲线上]显示了如何使用Python自己检查。变量x和y是如上所述的点Q的坐标。变量p是椭圆曲线的素数阶(用于所有mod运算的素数)。Python的最后一行是椭圆曲线方程(Python中的%运算符是mod运算符)。如果x和y确实是椭圆曲线上的点,那么它们满足等式并且结果为零(0L是值为零的长整数)。通过在命令行上键入python并从列表中复制每一行(在提示>>>之后)自己尝试:
示例1.使用Python确认此点位于椭圆曲线上
Python 3.4.0 (default, Mar 30 2014, 19:23:13)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.38)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> p = 115792089237316195423570985008687907853269984665640564039457584007908834671663
>>> x = 49790390825249384486033144355916864607616083520101638681403973749255924539515
>>> y = 59574132161899900045862086493921015780032175291755807399284007721050341297360
>>> (x ** 3 + 7 - y**2) % p
0L
椭圆曲线算术运算
很多椭圆曲线的数学看起来非常像我们在学校学到的整数运算。具体来说,我们可以定义一个加法运算符,而不是添加数字就是在曲线上添加点。一旦我们有了加法运算符,我们还可以定义一个点和一个整数的乘法,这样它就相当于多重加法
定义加法使得在椭圆曲线上给定两个点和,在椭圆曲线上也存在第三点。
几何上,通过在和之间画线来计算该第三点。该线将在一个额外的位置与椭圆曲线相交。称此点为。然后在x轴上反射得到。
在椭圆曲线数学中,有一个称为“无限远点”的点,它大致对应于数字零的作用。在计算机上,它有时用x = y = 0表示(它不满足椭圆曲线方程,但它是一个可以检查的简单的独立案例)。有几个特殊情况可以解释“无限远点”的必要性。
如果和是相同的点,则“和之间的线” 应该延伸到该点处曲线上的切线。该切线将恰好与一个新点相交。您可以使用微积分来确定切线的斜率。这些技术奇怪地起作用,即使我们用两个整数坐标来限制我们对曲线上的点的兴趣!
在某些情况下(即,如果和具有相同的x值但y值不同),则切线将完全垂直,在这种情况下, =“无限远点”。
如果是“无限远点”,那么。类似地,如果是无穷远处的点,那么。这显示了无限远处的点如何扮演零在“正常”算术中扮演的角色。
事实证明,+是关联的,这意味着(A + B)+ C = A +(B + C)。这意味着我们可以在没有括号的情况下编写A + B + C而且没有歧义。
现在我们已经定义了加法,我们可以用扩展加法的标准方式定义乘法。对于椭圆曲线上的点P,如果k是整数,则k * P = P + P + P + ... + P(k次)。注意,在这种情况下,k有时会被混淆地称为“指数”
生成公钥
以一个随机生成的数字k形式的私钥开始,我们用曲线上的一个预定点G乘以它,得到曲线上的另一个点,也就是对应的公钥K。生成器点被指定为secp256k1标准的一部分,对于secp256k1的所有实现和从该曲线导出的所有密钥都使用相同的点G:
其中k是私钥,G是生成器点,K是结果公钥,即曲线上的一个点。因为生成器点总是同一Ethereum所有用户私钥k乘以G,总是会导致相同的公钥k。k和K之间的关系是固定的,但只能在一个方向上进行计算,从k到K。这就是为什么以太坊地址(从K派生)可以与任何人共享并且不会泄露用户的私钥(k)。
正如我们在椭圆曲线算术运算中所描述的,k * G的乘法等价于重复的加法,所以G + G + G +…+ G,重复k次。总之,要从私钥k中生成公钥K,我们将生成器点G加上它自己,K次。
Tip | 可以将私钥转换为公钥,但不能将公钥转换为私钥,因为计算方法只有一种。 |
---|
让我们应用此计算来查找我们在私钥中显示的特定私钥的公钥:
示例公钥计算的私钥
K = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315 * G
加密库可以帮助我们使用椭圆曲线乘法计算K。生成的公钥K定义为点K =(x,y):
示例公钥由示例私钥计算
K = (x, y)
where,
x = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b
y = 83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
在以太坊中,您可能会看到公钥表示为66个十六进制字符(33个字节)的十六进制序列化。这是从高效密码学标准行业协会(SECG)提出的标准序列化格式中采用的,在高效密码学标准(SEC1)中有记录。该标准定义了四个可用的前缀,可用于识别椭圆曲线上的点:
前缀 | 含义 | 长度(前缀的字节数) |
---|---|---|
0x00 | 无穷点 | 1 |
0×04 | 未压缩点 | 65 |
0x02 | 偶数Y的压缩点 | 33 |
0x03 | 奇数Y的压缩点 | 33 |
以太坊仅使用未压缩的公钥,因此唯一相关的前缀是(十六进制)04。序列化连接公钥的X和Y坐标:
04 + X-coordinate (32 bytes/64 hex) + Y coordinate (32 bytes/64 hex)
因此,我们在[示例公钥由示例私钥计算]中计算的公钥被序列化为:
046e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
椭圆曲线库
在加密货币相关项目中使用了几个secp256k1椭圆曲线的实现:
OpenSSL
OpenSSL库提供了一套全面的加密组件,包括secp256k1的完整实现。例如,为了导出公钥,可以使用函数EC_POINT_mul()。在https://www.openssl.org/上找到它
libsecp256k1
Bitcoin Core的libsecp256k1是secp256k1椭圆曲线和其他加密组件的C语言实现。椭圆曲线加密的libsecp256是从头开始编写的,用Bitcoin Core软件取代OpenSSL,在性能和安全性方面都被认为是优越的。在以下网址找到它:
https://github.com/bitcoin-core/secp256k1
加密哈希函数
在以太坊中使用加密哈希函数。实际上,哈希函数在几乎所有的加密系统中都被广泛使用,这是由密码学家Bruce Schneier得出的事实,他说“不仅仅是加密算法,单向哈希函数是现代密码学的主力”。
在本节中,我们将讨论哈希函数,理解它们的基本属性以及这些属性如何使它们在现代密码学的许多领域中如此有用。我们在这里解释哈希函数,因为它们是将以太网公钥转换为地址的一部分。
简单来说,“哈希函数是可用于将任意大小的数据映射到固定大小的数据的任何函数。” 资料来源:维基百科。哈希函数的输入称为pre-image或message。输出称为hash或digest。哈希函数的一个特殊子类是加密哈希函数,它具有对加密有用的特定属性。
加密哈希函数是单向哈希函数,它将任意大小的数据映射到固定大小的字节字符串,如果知道输出,则重新创建输入在计算上是不可行的。确定输入的唯一方法是对可能的输入进行暴力搜索,检查匹配的输出。
加密哈希函数有五个主要属性(来源:维基百科/加密哈希函数):
确定性
任何输入message始终生成相同的哈希摘要。
可验证
计算message的hash是有效的(线性性能)。
不相关
对message的一个小更改(例如,一个字节更改)应该对哈希输出进行很大的更改,以至于它不能与原始message的哈希相关联。
不可逆性(第一原像阻力)
从哈希计算message是不可行的,相当于通过可能的message进行暴力搜索。
碰撞保护(第二原像阻力)
计算产生相同哈希输出的两个不同message应该是不可行的。
第二原像阻力,对于防止在以太的数字签名伪造是很重要的。
这些属性的组合使得加密哈希函数对广泛的安全应用程序有用,包括:
- 数据指纹识别
- 消息完整性(错误检测)
- 验证的工作
- 身份验证(密码哈希和密钥扩展)
- 伪随机数发生器
- 原像承诺(Pre-image commitment)
- 唯一标识符
随着我们在系统的各个层面上进展,我们将在以太坊中找到许多这些。
以太坊的加密哈希函数 - Keccak-256
以太坊在许多地方使用Keccak-256加密哈希函数。Keccak-256被设计为2007年由国家科学技术研究所(NIST)举办的SHA-3密码哈希函数竞赛的候选人。Keccak是获胜的算法,在2015年被标准化为联邦信息处理标准(FIPS)202。
然而,在以太坊开发期间,NIST标准化正在最终确定。NIST在标准流程完成后调整了Keccak的一些参数,据称是为了提高其效率。这是在英雄告密者爱德华·斯诺登透露文件的同时发生的,这些文件暗示NIST可能受到国家安全局的不当影响,故意削弱Dual_EC_DRBG随机数发生器标准,有效地在标准随机数发生器中放置后门。这一争议的结果是对提议的变更的强烈抵制以及SHA-3标准化的显着延迟。当时,以太坊基金会决定实施其发明人提出的原始Keccak算法,
Warning | 虽然您可能会在以太坊文档和代码中看到“SHA3”,但很多(如果不是全部)实例实际上都是指Keccak-256,而不是最终的FIPS-202 SHA-3标准。实现差异很小,与填充参数有关,但它们的重要性在于Keccak-256在给定相同输入的情况下产生与FIPS-202 SHA-3不同的哈希输出。 |
---|
由于以太坊(Keccak-256)中使用的哈希函数与最终标准(FIP-202 SHA-3)之间的差异所造成的混淆,现在正在努力将所有代码、操作码和库中的sha3实例重命名为keccak256。有关详细信息,请参阅ERC-59。
我使用了哪个哈希函数?
如果两者都被称为“SHA3”,你怎么知道你使用的代码库是FIPS-202 SHA-3还是Keccak-256?
一种简单的方法是使用测试向量,即给定输入的预期输出。最常用于哈希函数的测试是空输入。如果您使用空字符串作为输入运行哈希函数,您应该看到以下结果:
测试您使用的SHA3库是否为FIP-202 SHA-3的Keccak-256
Keccak256("")=
c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470
SHA3("")=
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
因此,无论调用什么函数,您都可以通过运行上面的简单测试来测试它是否是原始的Keccak-256,或最终的NIST标准FIPS-202 SHA-3。请记住,以太坊使用Keccak-256,即使它在代码中通常称为SHA-3。
接下来,让我们来看看以太坊中Keccak-256的第一个应用,即从公钥生成以太坊地址。
以太坊地址
以太坊地址是使用单向哈希函数(特别是Keccak-256)从公钥或合约派生的唯一标识符。
在前面的示例中,我们从私钥开始,并使用椭圆曲线乘法来派生公钥:
私钥k:
k = f8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
公钥K(X和Y坐标连接并显示为十六进制):
K = 6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
Warning | 值得注意的是,在计算地址时,公钥未使用前缀(十六进制)04格式化。 |
---|
我们使用Keccak-256来计算这个公钥的哈希值:
Keccak256(K)= 2a5bc342ed616b5ba5732269001d3f1ef827552ae1114027bd3ecf1f086ba0f9
然后我们只保留最后20个字节(big-endian中最不重要的字节),这是我们的以太坊地址:
001d3f1ef827552ae1114027bd3ecf1f086ba0f9
大多数情况下,您会看到前缀为“0x”的以太坊地址,表示它是十六进制编码,如下所示:
0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
以太坊地址格式
以太坊地址是十六进制数,是从公钥的Keccak-256哈希的最后20个字节派生的标识符。
与在所有客户端的用户界面中编码的比特币地址不同,包括内置校验和以防止输入错误的地址,以太网地址以原始十六进制形式呈现,没有任何校验和。
该决定背后的理由是,以太坊地址最终会隐藏在系统较高层的抽象(例如名称服务)之后,并且必要时应在更高层添加校验和。
回想起来,这种设计选择会导致许多问题,包括由于输入错误的地址和输入验证错误导致的资金损失。以太坊名称服务的开发速度比最初预期慢,钱包开发人员采用ICAP等替代编码非常缓慢。
国际交易客户端地址协议(ICAP)
国际交易客户端地址协议(ICAP)是一个以太坊的地址编码,与国际银行账户号码(IBAN)编码部分兼容,提供了一种通用的、可校验和互操作的Ethereum地址编码。ICAP地址可以编码以太坊地址或通过以太坊名称注册表注册的常用名称。
阅读以太坊Wiki上的ICAP:https://github.com/ethereum/wiki/wiki/ICAP:-Inter-exchange-Client-Address-Protocol
IBAN是识别银行账号的国际标准,主要用于电汇。它在欧洲单一欧元支付区(SEPA)及其他地区被广泛采用。IBAN是一种集中且严格监管的服务。ICAP是以太坊地址的分散但兼容的实现。
IBAN由最多34个字母数字字符(不区分大小写)字符串组成,其中包含国家/地区代码,校验和和银行帐户标识符(特定于国家/地区)。
ICAP通过引入代表“以太坊”的非标准国家代码“XE”使用相同的结构,然后是两个字符的校验和以及帐户标识符的3种可能变体:
- 直接:最多30个字母数字字符的big-endian base-36整数,表示以太坊地址的最低有效位。因为此编码小于155位,所以它仅适用于以一个或多个零字节开头的以太坊地址。优点是它在字段长度和校验和方面与IBAN兼容。示例:XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD(33个字符长)
- 基本:与“直接”编码相同,但长度为31个字符。这允许它编码任何以太坊地址,但使其与IBAN字段验证不兼容。示例:XE18CHDJBPLTBCJ03FE9O2NS0BPOJVQCU2P(35个字符长)
- 间接:对通过名称注册表提供程序解析为以太坊地址的标识符进行编码。使用16个字母数字字符,由资产标识符(例如ETH),名称服务(例如XREG)和9字符名称(例如KITTYCATS)组成,这是一个人类可读的名称。示例:XE ## ETHXREGKITTYCATS(长度为20个字符),其中“##”应替换为两个计算的校验和字符。
我们可以使用helpeth命令行工具来创建ICAP地址。让我们尝试使用我们的示例私钥(前缀为0x并作为参数传递给helpeth):
$ helpeth keyDetails -p 0xf8f8a2f43c8376ccb0871305060d7b27b0554d2cc72bccf41b2705608452f315
Address: 0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
ICAP: XE60 HAMI CDXS V5QX VJA7 TJW4 7Q9C HWKJ D
Public key: 0x6e145ccef1033dea239875dd00dfb4fee6e3348b84985c92f103444683bae07b83b5c38e5e2b0c8529d7fa3f64d46daa1ece2d9ac14cab9477d042c84c32ccd0
helpeth命令为我们构造十六进制以太坊地址和ICAP地址。我们的示例密钥的ICAP地址是:
XE60HAMICDXSV5QXVJA7TJW47Q9CHWKJD
因为我们的示例以太坊地址恰好以零字节开始,所以可以使用在IBAN格式中有效的“直接”ICAP编码方法对其进行编码。你可以说,因为它长33个字符。
如果我们的地址不是以零开头,则它将使用“基本”编码进行编码,该编码长度为35个字符,并且作为IBAN格式无效。
Tip | 任何以0字节开始的以太网络地址的概率是1/256。要生成这样一个密钥,我们平均需要256次尝试,使用256个不同的随机私钥,然后才能找到一个与IBAN兼容的“直接”编码的ICAP地址。 |
---|
目前,不幸的是,只有少数钱包支持ICAP。
大小写校验和的十六进制编码(EIP-55)
由于ICAP或名称服务的部署缓慢,因此提出了使用以太坊改进提案55(EIP-55)的新标准。您可以在以下位置阅读详细信息
https://github.com/Ethereum/EIPs/blob/master/EIPS/eip-55.md
EIP-55通过修改十六进制地址的大写,为以太坊地址提供向后兼容的校验和。这个想法是以太坊地址不区分大小写,并且所有钱包都应该接受以大写或小写字符表示的以太坊地址,而在解释上没有任何差别。
通过修改地址中字母字符的大小写,我们可以传达一个校验和,可用于保护地址的完整性,防止输入或读取错误。不支持EIP-55校验和的钱包忽略了地址包含混合大小写的事实。但那些支持它的人可以验证它并以99.986%的准确率检测错误。
混合大写的编码很微妙,一开始你可能不会注意到。我们的示例地址是:
0x001d3f1ef827552ae1114027bd3ecf1f086ba0f9
使用EIP-55混合大小写校验和,它变为:
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
你能分辨出来吗?十六进制编码字母表中的一些字母(AF)字符现在是大写字母,而其他字母则是小写字母。除非你仔细观察,否则你甚至可能没有注意到这种差异。
EIP-55实施起来非常简单。我们采用小写十六进制地址的Keccak-256哈希。此哈希充当地址的数字指纹,为我们提供方便的校验和。输入(地址)的任何微小变化都会导致产生的哈希(校验和)发生巨大变化,从而使我们能够有效地检测错误。然后将地址的哈希值编码为地址本身的大小写。让我们一步一步地分解它:
1.哈希小写地址,不带0x前缀:
Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0f9”)
23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9695d9a19d8f673ca991deae1
2.如果哈希的相应十六进制数字大于或等于0x8,则将每个字母地址字符大写。如果我们排列地址和哈希,这更容易显示:
地址:001d3f1ef827552ae1114027bd3ecf1f086ba0f9
哈希:23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9 ......
我们的地址在第四个位置包含一个字母字符d。哈希的第四个字符是6,小于8.因此,我们保留d小写。我们地址中的下一个字母字符是f,位于第六位。十六进制哈希的第六个字符是c,它大于8.因此,我们将地址中的F大写,依此类推。如您所见,我们只使用散列的前20个字节(40个十六进制字符)作为校验和,因为我们在地址中只有20个字节(40个十六进制字符)才能正确地大写。
自己检查生成的混合大小写地址,看看是否可以分辨哪些字符大写,以及它们在地址哈希中对应的字符:
地址:001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
哈希:23a69c1653e4ebbb619b0b2cb8a9bad49892a8b9 ......
检测EIP-55编码地址中的错误
现在,让我们看看EIP-55地址将如何帮助我们找到错误。假设我们已经打印出以太坊地址,这是EIP-55编码的:
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0F9
现在让我们在阅读该地址时犯一个基本错误。最后一个字符前面的字符是大写字母“F”。对于这个例子,让我们假设我们把它误读为大写“E”。我们在钱包里输入(错误的地址):
0x001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
幸运的是,我们的钱包符合EIP-55标准!它注意到混合大写并尝试验证地址。它将它转换为小写,并计算校验和哈希:
Keccak256( “001d3f1ef827552ae1114027bd3ecf1f086ba0e9”)
5429b5d9460122fb4b11af9cb88b7bb76d8928862e0a57d46dd18dd8e08a6927
正如您所看到的,即使地址仅改变了一个字符(事实上,“e”和“f”之间只相差1位),地址的哈希也发生了根本改变。这是哈希函数的属性,使它们对校验和非常有用!
现在,让我们排列并检查大小写:
001d3F1ef827552Ae1114027BD3ECF1f086bA0E9
5429b5d9460122fb4b11af9cb88b7bb76d892886 ...
这都错了!几个字母字符的大写不正确。请记住,大小写是正确校验和的编码。
我们输入的地址的大小写与刚刚计算的校验和不匹配,这意味着地址中的某些内容发生了变化,并且引入了错误。