主页 > www.token.im > #9 比特币地址算法详解 原文
#9 比特币地址算法详解 原文
学习了私钥和公钥生成算法后,在密钥和地址环节还剩下一个重要的算法,那就是地址生成算法。 学习之前,我们还是要问一个问题
有了公钥之后,为什么还需要比特币地址呢? 毕竟公钥和地址的本质是一样的,都是为了证明私钥持有者发起了一笔交易,而没有传输私钥。
其实这就像我们可以通过姓名、性别、身高、体重来描述一个人,我们也可以通过这个人唯一的特征——指纹来识别他。比特币的公钥是椭圆曲线上的一个点。 这个点的x值和y值往往很大,这无疑让我们很难使用公钥,所以就有了地址address,也就是公钥的指纹。 它简化了使用比特币的复杂性,让我们看一个例子
# 比特币公钥
0340d2b832dfe3ec2d2b1ff9d0dfdfb9599d12344c6c0308a107a0782ebe21d865
# 比特币地址
1G7cNFwW6tbXah6LBUDn8TPdsMhYvoBT9Y
可以看出,比特币地址的字符长度几乎比公钥短一半。 如何做到这一点,就是我们今天要学习的内容。
公钥生成步骤
从比特币公钥和地址这两个字符串可以看出,公钥的生成算法无非就是把一个长字符串转换成另一个短字符串。 这个转换过程分为两个步骤。
通过哈希算法将公钥转化为定长字符串
压缩第一步的结果并输出地址
下图中的蓝色矩形分别对应每一步
散列过程
哈希(hash)函数是计算机科学中广泛使用的一类函数。 它可以将任何数据映射到指定范围的数据字段。 此映射过程是单向的。 比如我们可以把一个4GB的视频文件映射到一个8字节的数字,但是我们不能用这个数字来恢复视频。 评价一个哈希函数的标准是映射集越分散越好,越集中越差。
在比特币中,哈希函数用于比特币地址、脚本地址和工作量证明。 比特币地址的生成使用了两种哈希函数,一种是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的结果。 我建议你也操作它来加深这个形象。
压缩编码过程
至此,生成比特币地址的工作已经完成了一大半,还差一步压缩编码。 所谓压缩编码就是用更少的字符来表示一个数字。 这里的压缩原理也很简单比特币地址查询网站,就是“十六进制比十进制短,十进制比二进制短”。
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(低L)、大I(大i),以及符号+和/,去掉这些字符的原因是很难区分在某些情况下,比如你向转账方发送一个包含0(零)的地址比特币地址查询网站,对方会认为是大写字母O,最终导致财产损失。
Base58 编码用于比特币地址、私钥和脚本哈希的上下文中。
Base58校验
尽管base58比base64更不容易出错,但仍然不能保证你不会出错。 有什么办法可以避免这些错误吗? 是的,在计算机中,我们通常会使用校验和来校验数字内容,校验和会作为内容的一部分提供,这样一旦内容有任何变化,计算出来的校验和就会与该内容不一致原始校验和,同样是的,比特币地址也包含校验和,用于验证地址是否被错误复制或被修改。
为了直观的展示这个过程,我们看下面一个简单的例子。 假设一串数字是“1215309”,校验和算法是每个数字的和,即“21”,那么将这两串字符拼接起来,就形成了一个自验证串“121530921”。 假设我们在传输这串内容的时候不小心把第二个字符的2写成了5,那么在校验的时候会计算校验和为24,与最后提供的21不匹配,校验失败。
有了这些基础,我们就可以看一下Base58Check的编码过程,分为4个步骤,如下图
在20字节公钥Hash的基础上,增加版本号前缀,输出新的字符串
使用SHA256算法对步骤1生成的字符串进行两次哈希,取结果的前4个字节作为Checksum
将 Checksum 作为后缀添加到公钥 Hash 的末尾
对整个字符串进行Base58压缩编码,生成比特币地址
步骤中的Version版本号前缀前面没有提到。 它的作用是直观区分这串字符的内容,因为除了地址,Base58编码还可以用在私钥和脚本哈希中。 下表是不同Version代表的含义
Type版本前缀(十六进制表示)版本前缀(Base58表示)
比特币地址
0x00
1个
脚本哈希地址
0x05
3个
比特币测试网地址
0x6F
中号或中号
私钥 WIF
0x80
5、K 或 L
BIP-38加密私钥
0x0142
6P
BIP-32 扩展公钥
0x0488B21E
xpub
看完这张表,你就知道为什么比特币地址都是1开头的了。
总结
本文介绍了为什么要引入比特币地址,并详细描述了生成比特币地址的步骤,即
散列过程
base58编码过程
相关文章: