玩币族移动版

玩币族首页 > 币圈百科 >

[技术流]深入理解比特币地址与私钥:比特币公钥与私钥算法学习

  比特币具有许多革命性的特征,让比特币爱好者们成为她的死忠。去中心化特征是最具影响力的,货币发行和交易的实现采用p2p网络争夺记账权完美地实现了去中心化。这里有一个大家熟知的51攻击方式可以导致比特币终结,关于这方面的论述已经有很多,我不准备再哆嗦一遍。比特币还有一个非常重要的特征:使用非对称加密的方法保证其安全性,这个特征如果被推翻的话也意味着比特币的终结。密码学的安全性被推翻可以有两个途径:一是从加密原理上找到加密算法本身的漏洞而破解;二是使用高算力的计算机对公钥进行反算。非对称加密算法自提出到现在也没有找到漏洞,也许它根本就没有漏洞,那些讨论加密算法漏洞的也最多就是随机数生成的漏洞,这并非是加密算法本身的漏洞,只是加密算法的工作前提没有得到保证而已。我始终认为高算力的计算机才是比特币最大的威胁,比如炒得火热的量子计算机,究竟量子计算机会牛到什么程度我不清楚,目前我只能站在这种普通二进制计算机的角度来分析如何进行公钥反算。

  1.比特币地址和私钥的生成

  比特币使用椭圆曲线算法生成公钥和私钥,选择的是secp256k1曲线。生成的公钥是33字节的大数,私钥是32字节的大数,钱包文件wallet.dat中直接保存了公钥和私钥。我们在接收和发送比特币时用到的比特币地址是公钥经过算法处理后得到的,具体过程是公钥先经过SHA-256算法处理得到32字节的哈希结果,再经过RIPEMED算法处理后得到20字节的摘要结果,再经过字符转换过程得到我们看到的地址。这个字符转换过程与私钥的字符转换过程完成相同,步骤是先把输入的内容(对于公钥就是20字节的摘要结果,对于私钥就是32字节的大数)增加版本号,经过连续两次SHA-256算法,取后一次哈希结果的前4字节作为校验码附在输入内容的后面,然后再经过Base58编码,得到字符串。

  图一、比特币地址和私钥的生成

  这里需要提一下的是Base58编码为了让输出字符串易于辨别,所以编码时故意排除了4个字符: ‘0’、‘I’、‘l’、‘O’,如果你想生成一个带特殊词缀的地址那就不要带这4个符了,比如我的ID(walker)也就不能生成了。

  2.比特币地址生成工具

一开始我是打算自己写一个比特币地址生成工具来生成自己喜欢的地址,当然我确实也这样做了,也做出来了。我最初的想法是尽量利用bitcoin-qt的代码,因为这样生成的比特币地址就如同bitcoin-qt自身生成的一样,避免像某些在线钱包和Android钱包那样的随机数漏洞。这份源码包含VS2005的工程,代码去掉了对boost的依赖,但依赖OpenSSL是必不可少的,所以你要编译的话前提是需要有OpenSSL。主循环里只包含简单的比特币地址生成逻辑,如果你对生成过程感兴趣,这代码非常适合你阅读。

  图二、比特币地址生成代码类图

  不过后来我发现了一个比特币地址生成工具vanitygen,这一个华盛顿大学的学生写的,用的是C语言,写得非常赞。【原文链接】vanitygen通过设置不同的参数就可以使用各种强大的功能,他的帖子还输出了效率测试报告,真的是太周到了。不过让我抛弃自己写的工具的主要原因是它的执行效率非常高,在我的机器上使用单线程全速运行的情况下,vanitygen能达到150KKeys/s,而我的工具只能达到0.5KKeys/s。当然原因很简单,我的代码里做了多次对象复制,不过也因为这样你会发现面向对象的代码非常易读。

  3.比特币寻宝机

  比特币地址可以批量生成,并去命中一定的字符组合,这一定能让人联想到去命中已明确丢失私钥又包含巨款的地址,比如:167ZWTT8n6s4ya8cGjqNNQjDwDGY31vmHg,当然,心狠一点的也想去命中土豪的地址,比如:1933phfhK3ZgFQNLGSDXvqCn32k2buXY8a。我在这里称这种地址为“宝藏”,究竟哪些地址是宝藏,有多少钱宝藏,其实这很方便查找,因为比特币的数据链就是完整又公开的寻宝图,通过分析数据链就可以得出哪些地址是宝藏,也可以知道宝藏的丰厚程度。在MtGox开市后一直没有活动过地址,我们可以认定为遗失的宝藏,这正是寻宝机所要寻找的目标。

  好了,再说寻宝机吧。可以设计一种ASIC芯片,快速地生成比特币地址,然后与遗失的宝藏进行对比,有命中的话就产生中断。芯片模块设计图如下:

  图三、寻宝机ASIC芯片模块设计图

  ASIC矿机反复使用SHA-256算法寻找一个满足难度要求的哈希结果,算法的输入是全网所有的交易清单,这个输入的数据量是相当庞大的,而寻宝机的SHA-256算法输入只有33个字节,相对于ASIC矿机而言数据量非常小,所以同等规模的ASIC,寻宝机的地址生成速率会比矿机的哈希速率要快。

  但是我需要说明一下,上图所示的这种芯片只是一个概念模型,它顶多能做如vanitygen所做的事,生成个漂亮带词缀的个性化地址,如果想依赖于它来命中一个宝藏,我认为无异于痴人说梦。接下来讨论寻宝机命中机率。

  4.寻宝机命中机率分析

  一个比特币地址由字符’1′再加上33个字符构成,这33个字符的每一个字符可能是58个字符中的一个(注意不是62,前面提到Base58编码把4个字符排除在外了),那是不是意味着单次生成地址的命中机率是58的33次方分之一呢 不是这样的!

  请看这一个地址,1BitcoinEaterAddressDontSend,不要怀疑,它确实是一个有效的比特币地址,并且里面还有币,是个实实在在的宝藏。需要说明,这不是一个正规渠道生成出来的地址,这个地址的诞生完全是为了证明比特币发送的工作原理,比特币发送时只验证比特币地址的合法性。

  众所周知,只要知道对方的比特币地址就可以给对方发送一定数量的比特币过去,但是SHA-256算法是不可逆的,通过比特币地址反算,最多也就只能得到20字节的摘要结果。从代码wallet.cpp第1144行,CWallet::CreateTransaction()中可以看出,发送比特币的消息里也是放的对方公钥经过RIPEMED算法处理后得到20字节的摘要结果。只要你得到的私钥能算出完全相同的20字节的摘要结果,那你的私钥就与这个地址配对了,你就成了这个宝藏的拥有人之一。

  这样一来可以得出一个结论,单次生成地址的命中机率是256的20次方分之一。256的20次方分之一可是要比58的33次方分之一小10个数量级。

  寻宝机率受两个变量的影响:地址生成速率和预命中的宝藏个数。

  GenRate * KeyCount

  P = ——————————-

  256^20

  从上面的公式可以看出,如果你想要尽快的得到宝藏,那需要想方设法地提到那两个变量的值,一是加快地址生成速率,一是确定尽量多的宝藏。

  随着比特币越来越广泛的应用,以后必要会出来平均每地址的比特币数量下降,余额大于0的比特币地址越来越多,也意味着命中的机率会越来越大。如前文所述,余额大于0的比特币地址可以从公开的数据链中得出,只需要开发一个遍历数据链的工具,动态刷新宝藏列表即可。接下来讨论加快地址生成速率的一种方法。

  5.分布式网络寻宝

  和挖矿是同样道理,单独一台寻宝机可能一辈子也找不到一块宝藏,如果集全网络所有人的力量分布式寻宝的话,机率就会大太多,这样一旦寻到宝藏就可以公平的按地址生成速率分配给大家,多少有些海盗分金的味道。

  不过这种分布式网络寻宝需要重新设计ASIC,把地址生成芯片和地址对比芯片设计得更专用。芯片各功能模块如下图所示:

  图四、地址生成ASIC芯片模块设计图 图五、地址对比ASIC芯片模块设计图

  地址生成芯片把生成的地址组成一个地址包接近MTU大小,提高网络利用率;地址对比芯片的功能更简单,处理效率会很高,所以为保证处理的流畅性需要进行输入整流。

  分布式网络寻宝的结构如下图所示:

  图六、分布式网络寻宝结构图

  地址集中处理服务器充当中介者角色,负责从全网上收集生成的地址包、从数据链中查出宝藏、配置地址对比芯片、接收处理对比结果。

  6.展望

  就目前比特币的流程程度和ASIC和处理能力来看,想要命中一个宝藏还非常困难的。假设全网算力为1000P,1M的地址,那要成功命中一个宝藏的时间理论值为47515528679349475857年。要想让寻宝机得到实现,还是需要等待极高算力设备的出现。

  如果真有哪一天比特币寻宝机诞生,那绝对是比特币的终结之日,就目前而言,大家可以放心地使用比特币。

知识: 私钥 公钥 比特币地址