在《精通比特币》这本书里有一张经典的图,用来说明私钥、公钥和比特币地址三者之间的关系。私钥可以生成公钥,公钥再生成比特币地址,反过来皆不可行。
摘自《精通比特币》
在区块链的世界里,我们持有的比特币只是一串私钥,一串256位的二进制数。如果你扔硬币,正面记为0,反面记为1,连扔256次,把它记录下来,再把这串二进制数值转换为十六进制数,你的所有家当就在这串私钥上了。
假设我有这样一串随机数:
3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8
为了让你看清楚它的字节数,我加了一条标尺,256位,64个十六进制数,32个字节。
代码语言:javascript复制----.----1----.----2----.----3----.----4----.----5----.----6----
3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8
现在要把这串私钥生成比特币地址。首先准备一个命令行工具小软件Bitcoin Explorer,这款软件可以运行在Linux,Mac和Windows等操作系统上,下载的网址:
https://github.com/libbitcoin/libbitcoin-explorer/wiki/Download-BX
软件非常小巧,只有一个文件,我为了方便输入,把文件名改为bx.exe。
私钥生成公钥
打开一个cmd命令行窗口,运行如下命令。
为了方便说明,我把命令和返回结果重新排版:
代码语言:javascript复制bx ec-to-public -u 3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8
运行结果如下:
----.----1----.----2----.----3----.----4----.----5----.----6----
04
2e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8b
b119f9161df032167181d623a401dde4091c3e0be2001e4dea3e1f53f851aa3a
ec-to-public的 EC是指Elliptic Curve,即椭圆曲线,比特币的加密算法中用到了复杂的椭圆曲线加密,简单来说,就是一串数字,经过加密之后,变换到椭圆曲线上的一个点,这个点有x坐标和y坐标。
返回结果有65个字节。
第一个字节04,表示是非压缩的公钥格式。
紧跟着32个字节,是x坐标。
再跟着32个字节,是y坐标。
椭圆曲线的原理实在太烧脑,我一路研究下去,发现与费马大定理关系紧密,然后入迷般地把《费马大定理》这本书也看完了,万物间存在着巧妙的联系,没想到椭圆曲线又被中本聪应用于比特币的加密算法中。
图片摘自czbaa.com
不管这些原理,我们刚才得到的65个字节的042e88......51aa3a这串数值就是公钥。而从这个公钥出发,反推回私钥是几乎不可能的。
公钥生成地址
原理图如下,摘自《精通比特币》。
这里需要再运行bx sha256、bx ripemd160以及bx address-encode三个命令,最后生成的比特币地址为 17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf
SHA是Secure Hash Algorithm的缩写,SHA256表示生成的结果为256位的二进制数。经过这一层哈希之后,相当于又做了一次加密。
RIPEMD代表the RACE Integrity Primitives Evaluation Message Digest,256位稍微有点长,用这个算法之后,得到一个长度为160比特(20字节)的数。
本文例子中得到了 4a32d744feaa62eb017674b6a4f5dce397f6b1b9
最后一步加上了校验码和base58编码,防止人工输入错误,这个地址里永远不可能有0(数字0)、O(大写字母o)、l(小写字母L)、I(大写字母i),我们的例子里得到了地址 17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf
完整的命令行:
代码语言:javascript复制bx ec-to-public -u 3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8 | bx sha256 | bx ripemd160 | bx address-encode
运行结果:
042e88d239fb78cee0c1c55943a96dcc8b70adf47e18b53f9ba110b6fb871e1f8bb119f9161df032167181d623a401dde4091c3e0be2001e4dea3e1f53f851aa3a
74c743476f536592d64c38d75dfa676fa6d05e5fc5363bde5f7699336c3b6b51
4a32d744feaa62eb017674b6a4f5dce397f6b1b9
17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf
地址重合了?
到blockchain.info里看看这个地址里是否有比特币?访问网址:
https://blockchain.info/address/17mKugcBDEJbu391Fq41AdwLeGHwJLPRDf
这个地址中竟然有4笔历史交易,最近的一笔交易发生于2014年年底,难道是我扔出的256位的随机数中了彩票?
不可能,任意2个人随机生成的地址正好相同的可能性相当于2个人从地球上捡起了同一粒沙子,再把这粒沙子看做地球,相当于2个人又从这个地球里捡起了同一粒沙子。
为什么我生成的比特币地址与别人的地址重合了?因为我的256位随机数并不随机,而是来自于圆周率π = 3.1415926535897932384626的十六进制表示。
3.243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8
所以保证比特币安全的一条重要原则就是:一定要用真随机数作为私钥。
在Bitcoin Core等钱包里,随机数生成算法已经非常专业,重合的概率为0,可以放心使用。
如何将私钥导入钱包?
256位的数字不能直接在Bitcoin Core钱包里使用,需要转换为WIF格式,需要用到下面的命令。
bx ec-to-wif -u 3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8
返回的结果:
5JCRYcJrKGLTK6R3PbHopfY9BRdmtrq5TCTesx7x9mQUDeYDfZj
在Bitcoin Core时运行importprivkey命令就可以导入指定的私钥,查看余额了。
--- END ---