每天进步一点点: 比特币的公钥压缩与地址

in #cn7 years ago

在昨天的帖子中,学习了如何由私钥生成公钥.

有朋友私下问我,你咋整出俩公钥啊,一个压缩,一个未压缩,这又是什么鬼?我该用哪个公钥啊?别急,听我慢慢道来。

公钥压缩

为何要压缩

根据我们上节学习的成果,公钥(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随机数),那么我向一个地址打一笔钱过去,是两个地址同时显示有钱,还是只是我打钱的地址有钱呢?
我一会用我生成的这俩地址打一个比特币过去测试一下,你们别乱动啊。😭


今天就探索到这里。
免责声明,本文为个人理解,示例仅供参考
因使用文中代码或地址造成的损失,概不负责!

Sort:  

又一篇超級專業的文章!😆

过奖了,我也在学习和探索

Good....
Upvote & follow me....

done, pls follow me too

great post,awesome work
thanks for sharing the info.

请教一下,根据圆锥曲线y^2=x^3+7,一个确定的x不是应该生成两个y值吗(y1=-y2),那这个pubkey压缩的时候应该会有信息损失吧?不知道比特币系统是怎么解决的?

nice post...upvoted and followed ..... please me too

thank you for this useful info and article.

You are welcome! 😄

it's good that steemit can display translated page immediately , good to learn many things along the way..

學習了,多謝O哥。

😄 互相学习

哥 下篇探讨下荣耀地址生成呗

荣耀地址是啥?😄 华为的荣耀吗?

就是比特币地址靓号
有的人比特币地址是88888888888jdjdj 这种


我第一次听说,了不起

内容太高级了, 不是很看得懂,反正觉得不错!

谢谢夸奖 😄