在昨天的帖子中,学习了如何由私钥生成公钥.
有朋友私下问我,你咋整出俩公钥啊,一个压缩,一个未压缩,这又是什么鬼?我该用哪个公钥啊?别急,听我慢慢道来。
公钥压缩
为何要压缩
根据我们上节学习的成果,公钥(K)是通过私钥(k)乘以生成点(G)得到的,并且是椭圆曲线上的一个点P(x, y)
上图是我们用Hello World生成的私钥并计算出来的点P
表示成公钥其实就是把加上前缀04并把x和y连接起来
很长很长有木有,一共是520bits (8 + 256 + 256),使用16进制字符串表示,要130个字节!!
而这么长的内容在网上传输来传输去,传输无数次是很浪费资源的,于是就有了压缩的公钥
为何能压缩
通过以前的学习和上边的分析,我们知道公钥是椭圆曲线上的一个点P(x, y)
而按照椭圆曲线的方程,我们是可以通过x求得y的,所以我们只要保留x部分就可以了
机制就是这么简单!可见数学有多么重要,可惜是我从小学起就没有好好学 😭
同学们千万不要学我!
如何去压缩
以下图示很好的说明了公钥压缩的流程
公钥压缩的示意图( Source: 《Mastering Bitcoin》)
比特币地址
好了,公钥压缩问题已经理解了。
我们继续来进行最后一步,生成比特币地址!!!!
私钥、公钥都有了, 但是要玩转,让别人给我打钱,必须要有地址啊
木有地址,怎么骗钱???, 怎么收钱?
公钥到比特币地址的示意图( Source: 《Mastering Bitcoin》)
《Mastering Bitcoin》好书啊,再次强烈推荐!!
有了这个公钥到比特币地址的流程,生成比特币地址就相当容易了。
从steem python库中扒来ripemd160函数,hashlib真强大啊
def ripemd160(s):
ripemd160 = hashlib.new('ripemd160')
ripemd160.update(unhexlify(s))
return ripemd160.digest()
连扒再改弄个了生成地址的函数,请忽略变量命名之类的毛病
def get_address(public_key):
pkbin = unhexlify(public_key)
addressbin = ripemd160(hexlify(hashlib.sha256(pkbin).digest()))
address = base58CheckEncode(0x00, hexlify(addressbin).decode('ascii'))
return address
运行我们代码,导入之前生成的两组公钥,得到两个地址:
Address(C): 1LGWpj3pqbzYWvTLEcBKP6CS5PQkxBgjXj
Address(U): 14EvJWPvFNLnzBBzhm1AG9a5b6XiSBFs6R
验证
导入WIF(未压缩)
在blockchain.info 在线钱包,导入WIF(未压缩)
5K5CpQZtUvPqwk2UE1FAiWC1nPV1WYqMnEhMYy2WTiMz3J1u9nm
再导出私钥,显示的地址是未压缩的,但是私钥自动给显示成WIF-Compressed了
Address(U): 14EvJWPvFNLnzBBzhm1AG9a5b6XiSBFs6R
导入WIF-Compressed
在blockchain.info 在线钱包,导入WIF-Compressed
L2mZAF2AEEfq2cuVAQ5XtBqcTLEdFRWSifT7i6Hf2uZckefDJfp5
再导出私钥,显示的地址是压缩的,私钥显示和我们导入的相同
Address(C): 1LGWpj3pqbzYWvTLEcBKP6CS5PQkxBgjXj
不同的私钥(压缩、未压缩) 对应不同的地址
由此可见,不同的私钥(压缩或者未压缩)对应不同的比特币地址,和我们程序中生成的地址结果一样
钱包里虽然把私钥都作为WIF-Compressed显示,但是对于压缩和未压缩的,是区别对待的。
关于压缩私钥,压缩地址,以及压缩公钥
无论是压缩私钥还是压缩地址,地址和私钥本身是不压缩的,只是代表对应的公钥是压缩的而已
总结
- 公钥压缩可以节省空间
- 公钥压缩的原理: 对应椭圆曲线上的点P(x, y) , 可以通过x求得点y
- 公钥压缩的实现,y是偶数用02做前缀,奇数03,接上x的16进制字符串表示
- 比特币地址由公钥按固定流程生成
- 压缩公钥生成对应压缩公钥的地址
- 未压缩公钥生成对应未压缩公钥的地址
- blockchain.info 导入相同私钥的WIF, WIF-Compressed,生成两个地址
- 地址和私钥本身是不压缩的,只是代表对应的公钥是压缩的而已
疑问,两个地址对应的是一个私钥(256bit随机数),那么我向一个地址打一笔钱过去,是两个地址同时显示有钱,还是只是我打钱的地址有钱呢?
我一会用我生成的这俩地址打一个比特币过去测试一下,你们别乱动啊。😭
今天就探索到这里。
免责声明,本文为个人理解,示例仅供参考
因使用文中代码或地址造成的损失,概不负责!