学完 私钥 和公钥的生成算法后,在密钥和地址环节还剩一个重要的算法,那就是地址的生成算法,在学习之前,我们仍然要问一个问题
有了公钥后,为什么还要有比特币地址,毕竟公钥和地址的本质是一样的,都是为了在不传输私钥的前提下,证明某个交易是私钥持有人发起的。
其实这就好比我们可以从姓名、性别、身高及体重来描述一个人,我们也可以通过这个人的唯一特征对他进行确定——指纹。比特币的公钥是椭圆曲线上的一个点,这个点的 x
值和 y
值往往非常大,这无疑对我们使用公钥造成了困难,所以才会有地址 address
, 地址就是公钥的指纹,它简化了使用比特币的复杂度 ,我们来看一个例子
# 比特币公钥 0340d2b832dfe3ec2d2b1ff9d0dfdfb9599d12344c6c0308a107a0782ebe21d865 # 比特币地址 1G7cNFwW6tbXah6LBUDn8TPdsMhYvoBT9Y
可以看到,比特币地址的字符长度几乎比公钥短了一半,这是怎么做到的呢,这正是我们今天要学习的重点。
公钥的生成步骤
从比特币公钥和地址这两个字符串可以看出,公钥的生成算法无非是从一个长字符串转换为另一个短字符串,这个转化过程分为两步
-
通过哈希算法把公钥转换为一个定长的字符串
-
对第一步的结果进行压缩编码,输出地址
下图中蓝色矩形框分别对应着每一个步骤
哈希过程
哈希(hash)函数,是计算机学科中被广泛使用的一类函数,它可以把任意数据映射到指定范围的数据域中,这个映射过程是单向的,例如我们可以把一个4GB大小的视频文件映射为一个8个字节的数字,但反过来我们无法用这个数字把视频还原回来,评价一个哈希函数好坏的标准是映射集越分散越好,越集中越差。
在比特币中,哈希函数在比特币地址、脚本地址和工作量证明(Proof-Of-Work)中都有使用。比特币地址的生成中用了2个哈希函数,一个是 SHA256
(Secure Hash Algorithm),另一个是 RIPEMD160
(RACE Integrity Primitives Evaluation Message Digest)。这个过程是先使用 SHA256
把公钥映射为一个32字节的数字,再用 RIPEMD160
把产生的数字映射到一个20字节的数,见上图花括号中的内容。因为这两个算法都是公开的,所以很容易在计算机上模拟这个过程:
$ python Python 2.7.10 (default, Jul 15 2017, 17:16:57) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.31)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import hashlib >>> public_key = "0340d2b832dfe3ec2d2b1ff9d0dfdfb9599d12344c6c0308a107a0782ebe21d865" >>> step1 = hashlib.sha256(public_key).hexdigest() >>> hashlib.new('ripemd160', step1).hexdigest() '36239c6ea5a1bcc8d60f03a334c935993f689e5d'
上面是 Python
命令行对一个公钥分别执行 SHA256
和 RIPEMD160
的结果,建议你也操作一下,加深对此的映像。
压缩编码过程
至此,生成比特币地址的工作已经完成了一大半,还剩一步压缩编码的步骤,所谓压缩编码,就是用更少的字符来表示一个数字。这里的压缩原理也很简单,和“16进制比10进制短,10进制比2进制短”的道理是一样一样的。
10001000 # 2进制表示法,8个字符 136 # 10进制表示法,3个字符 0x88 # 16进制表示法,2个字符
比特币地址使用的压缩算法是 base58
算法,58代表每一位可以表示58个字符集,为什么是58个字符集这么奇怪?我们都听说过 base64
吧,没听过也不要紧,相信你一定见过这个
thunder://aHR0cDovL3Rvb2wubHUvdGVzdC56aXA=
上面是一个迅雷专有的下载链接,链接的 aHR0cDovL3Rvb2wubHUvdGVzdC56aXA=
部分就是用 base64
编码的,你现在可以打开一个在线的 base64
解码器,把这串字符解码,看一下原始字符串长什么样
理解了 base64
以后,再来理解 base58
就没那么困难了。 base58
是在 base64
的基础上去掉了6个字符的字符集,去掉的6个字符分别是0(零)、大O(欧)、小l(low L)、大I(big i)、符号+和/,去掉这些字符的原因是它们在某些情况下很难辨别,例如当你发送一个含有0(零)的地址给转账方,对方把它看成了大写的字母O,最终导致财产损失。
Base58
编码在比特币地址、私钥和脚本哈希的场景下都得到了运用。
Base58Check
即便 base58
比 base64
更难出错,但仍然不能保证你不出错,有没有什么手段能避免这些错误呢?有,在计算机中,我们通常用 checksum
来对数字内容作校验,同时 checksum
会作为内容的一部分提供出去,这样一旦内容有任何变更,这段内容计算出来的 checksum
和原 checksum
就会不一致,同样的,比特币地址中也含有 checksum
,来校验地址是否被抄错了,或被修改了。
为了直观的展现这个过程,下面我们来看一个简单的例子,假设一串数字内容为 "1215309"
, checksum
的算法为每一位的数字之和,即 "21"
,那么把这两串字符拼接起来,就构成了一个可自校验的字符串 "121530921"
,假设我们在传输这串内容时,不小心把第2个字符的 2
写成了 5
,那么在校验时,会算出 checksum
为 24
,和末尾提供的 21
不相符,校验失败。
有了这些基础,我们就可以来看一下 Base58Check
的编码过程了,它分为4个步骤,如下图所示
-
在20个字节的
公钥Hash
的基础之上,增加一个版本号前缀,输出一个新字符串 -
利用
SHA256
算法,对第1步产生的字符串进行2次哈希,取结果的前4个字节作为Checksum
-
将
Checksum
作为后缀加到公钥Hash
的尾部 -
对整个字符串进行
Base58
压缩编码,产生比特币地址
步骤中的 Version
版本号前缀是之前没有提及过的,它的作用是直观的区分这串字符的内容,因为除了地址外, Base58
编码还可以用于私钥和脚本哈希中,下面的表格是不同 Version
代表的含义
看了这个表格后,你再知道为什么比特币地址都是以 1
开头了把。
总结
本文介绍了为什么要引入比特币地址,及详细描述了比特币地址的生成步骤,即
-
哈希过程
-
Base58 编码过程
如果本文对你有帮助,欢迎关注我的公众号,或将本文分享给其他人。
相关文章:
「The Eye」是我建立的一个知识星球,这个名字 来自歌手Brandi Carlile的作品,"You can dance in a hurricane, But only if you’re standing in the eye.",预示着即便世界动荡不宁,但总有一个地方是我们的庇护所,因为我们的相聚,这里就是我们的台风眼。欢迎你的加入。
以上所述就是小编给大家介绍的《比特币地址算法详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。