主页 > 下载imtoken钱包 > #9比特币地址算法详解

#9比特币地址算法详解

下载imtoken钱包 2023-01-18 19:44:22

标题图

在学习了私钥和公钥的生成算法之后,在密钥和地址的环节还剩下一个重要的算法,那就是地址生成算法。在学习之前,我们还是要问一个问题。

拥有公钥后为什么还需要比特币地址?毕竟,公钥和地址的本质是一样的,都是为了证明一笔交易是由私钥持有者发起的,没有传递私钥。

其实这就像我们可以从名字、性别、身高和体重来描述一个人,我们也可以通过这个人唯一的特征——指纹来识别他。比特币的公钥是椭圆曲线上的一个点。这个点的x和y值往往很大,这无疑让我们很难使用公钥,所以有一个地址,就是公钥的指纹。它简化了使用比特币的复杂性,我们来看一个例子

# 比特币公钥
0340d2b832dfe3ec2d2b1ff9d0dfdfb9599d12344c6c0308a107a0782ebe21d865
# 比特币地址
1G7cNFwW6tbXah6LBUDn8TPdsMhYvoBT9Y

如你所见,比特币地址的字符长度几乎比公钥Half短,这是怎么做到的,这就是我们今天要学习的内容。

公钥的生成步骤

从比特币公钥和地址这两个字符串可以看出,公钥的生成算法无非就是将一个长字符串转换成另一个。一个短字符串,这个转换过程分为两步

比特币算法原理

通过哈希算法将公钥转化为定长字符串比特币算法原理,对第一步的结果进行压缩编码,输出地址

下图中的蓝色矩形对应每一步

哈希过程

哈希(hash)函数是计算机科学中广泛使用的一种函数。它可以将任意数据映射到指定范围的数据字段。此映射过程是单向的。例如,我们可以将一个 4GB 的视频文件映射到一个 8 个字节数,但反过来,我们不能使用这个数来恢复视频。评价哈希函数好坏的标准是映射集越分散越好,越集中越差。

在比特币中,哈希函数用于比特币地址、脚本地址和工作量证明。比特币地址的生成使用了两种哈希函数,一种是SHA256(安全哈希算法),另一种是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 编码用于比特币地址、私钥和脚本散列的上下文中。

Base58Check

比特币算法原理

尽管 base58 比 base64 更难出错,但它仍然不能保证你不会出错。有什么办法可以避免这些错误吗?是的,在计算机中,我们通常使用校验和来验证数字内容,校验和会作为内容的一部分提供,所以一旦内容有任何变化,从这个内容计算出来的校验和就会和原来的校验和不一致,同样是的,比特币地址也包含校验和,用于检查地址是否被复制错误或被修改。

为了直观的展示这个过程,我们来看一个简单的例子。假设一串数字的内容是“1215309”,校验和算法是每个数字的数字之和比特币算法原理,即“21”,那么这两个字符串拼接在一起形成一个自检查字符串“121530921”。假设我们在传输这串内容的时候不小心把第二个字符的2写成了5,然后check,会计算出校验和是24,和最后提供的21不匹配,说明内容发生了变化。

有了这些基础,我们可以看一下Base58Check的编码过程,分为4步,如下图所示

在20字节公钥Hash的基础上,添加版本号前缀,输出一个新的字符串,使用SHA256算法对步骤1生成的字符串进行两次hash,取前4个字节的结果用作校验和。 Checksum作为后缀添加到公钥Hash的末尾,整个字符串经过Base58压缩编码生成比特币地址。

步骤中有一个之前没有提到的版本前缀。并且,它的作用是从视觉上区分这串字符的内容,因为除了地址,Base58编码还可以用在私钥和脚本哈希中,下表是不同版本的含义

TypeVersion 前缀(十六进制表示)版本前缀(Base58 表示)

比特币地址

0x00

比特币算法原理

1

脚本哈希地址

0x05

3

比特币测试网络地址

0x6F

m 或 n

私钥 WIF

0x80

比特币算法原理

5、K 或 L

BIP-38 加密私钥

0x0142

6P

BIP-32 扩展公钥

0x0488B21E

xpub

看完这个表格,你就知道为什么比特币地址都是1开头了。

思考题

以太坊地址生成算法是否使用压缩编码过程?这种地址有什么问题?