精通比特币(四)钱包

目录

比特币钱包

非确定性(随机)钱包

确定性(种子)钱包

助记码词汇

助记码:熵及字段长度

分层确定性钱包(BIP0032/BIP0044)

从种子中创造HD钱包

私有子密钥的衍生(子私钥)

使用衍生的子密钥

扩展密钥(扩展私钥、扩展公钥)

扫描二维码关注公众号,回复: 12121741 查看本文章

子公钥推导

硬化子密钥的衍生

正常衍生和强化衍生的索引号码

HD钱包密钥识别符(路径)

HD钱包树状结构的导航

高级密钥和地址

加密私钥(BIP0038)

P2SH(Pay-to-Script Hash)和多签名地址

多重签名地址和P2SH

比特币靓号地址

纸钱包


比特币钱包

钱包是私钥的容器,通常通过有序文件或者简单的数据库实现。

另外一种制作私钥的途径是“确定性密钥生成”。可以用原先的私钥,通过单向哈希函数来生成每一个新的私钥,并将新生成的密钥按顺序连接。只要你可以重新创建这个序列,你只需要第一个私钥(称作种子、主私钥)来生成它们。

比特币钱包只包含私钥而不是比特币。每一个用户有一个包含多个私钥的钱包。钱包中包含成对的私钥和公钥。用户用这些私钥来签名交易,从而证明它们拥有交易的输出(也就是其中的比特币)。

比特币以交易输出的形式来储存在区块链中(通常记为vout或txout)

非确定性(随机)钱包

最早的一批比特币客户端中,钱包只是随机生成的私钥集合。这类型钱包被称作“零型非确定性钱包”。

举例,比特币核心客户端预先设定生成100个随机私钥,从最开始就生成足够多的私钥并且每把钥匙只是用一次。

这类型钱包有一个昵称“Just a Bunch Of keys”(一堆私钥) 简称 JBOK,这为用户的管理、备份、导入提供了工作量。现在逐渐被“确定性钱包”所替换。下图表示包含有松散结构的随机钥匙的集合的非确定性钱包。

特点是私钥之间互相没有任何联系,最早的比特币钱包就是这种类型。

在当时,要想备份钱包中的所有地址,必须对每个密钥对中的私钥进行单独备份,这样一来,备份管理就成了一件极其麻烦的事情。所以作为解决方案的确定性钱包应运而生。

确定性(种子)钱包

确定性,或者“种子”钱包包含通过使用单向散列方程而可从公共的种子生成的私钥。种子是随机生成的数字。这个数字也含有比如索引号码或者可生成私钥的“链码”。

在确定性钱包中,种子足够收回所有已经产生的私钥,所以只用在初始创建时的一个简单备份就足以搞定。

特点是所有密钥对都靠同一个种子产生。

确定性钱包的好处是:一个种子就能恢复所有的私钥,在备份和恢复起来都非常方便。值得注意的是,确定性钱包随机产出的种子是通过一系列确定、不可逆的运算来派生出一系列的密钥对。为什么要强调确定和不可逆?因为确定可以保证从一个种子中可以生成出全部的子密钥对,而“不可逆”则是为了确保不能通过子密钥对反推出种子。

助记码词汇

助记码词汇是英文单词序列代表(编码)用作种子对应所确定性钱包的随机数。

单词的序列足以重新创建种子,并且从种子那里重新创造钱包以及所有私钥。在首次创建钱包时,带有助记码的,运行确定性钱包的钱包的应用程序将会向使用者展示一个12至24个词的顺序。单词的顺序就是钱包的备份。他也可以被用来恢复以及重新创造应用程序相同或者兼容的钱包钥匙。助记码代码可以让使用者复制钱包更容易。因为相比较随机数字顺序,可以很容易被读出来并且正确抄写。

BIP0039是一个建议草案而非标准草案。具体说,电子钱包和BIP0039使用不同的标准且对应不同组的词汇。Trezor钱包以及一些其他钱包使用BIP0039,但是BIP0039和电子钱包的运行不兼容。

BIP0039定义助记码和种子的创建过程如下:

  1. 创造一个128到256位的随机顺序(熵);
  2. 提出SHA256哈希前几位,就可以创造一个随机序列的校验和。
  3. 把校验和加在随机顺序的后面。
  4. 把顺序分解成11位的不同集合,并用这些集合去和一个预先已经定义的2048个单词字典做对应。
  5. 生成一个12至24个词的助记码。

助记码:熵及字段长度

助记码表示128至256位数。这可以通过使用私钥抻拉函数PBKDF2来导出更长的(512位)的种子。所得的种子可以用来创造一个确定性钱包以及其所派生的所有钥匙。

如下展示了一些助记码的例子和它所生成的种子:

128位熵的助记码以及所产生的种子:

256位熵的助记码以及所产生的种子:

分层确定性钱包(BIP0032/BIP0044)

确定性钱包被开发成更容易从单个“种子”中生成许多关键的钥匙。最高级的来自确定性钱包的形式通过BIP0032标准生成的 HD(HD是Hierarchical Deterministic的缩写,意思是分层确定性。)。

分层确定性钱包包含从数据结构所生成的钥匙。这种母钥匙可以生成子钥匙的序列。这些子钥匙又可以衍生出孙钥匙,以此无穷。

HD钱包提供了随机(不确定性)钥匙,有两个主要优势:

  1. 树状结构可以被用来表达额外的组织含义。
  2. 它可以允许让使用者去建立一个公钥的序列而不需要访问相对应的私钥。这可允许HD钱包在不安全的服务器中使用或者在每笔交易中发行不同的公钥。

从种子中创造HD钱包

HD钱包从单个root seed中创建,为128到256位的随机数。HD钱包所有确定性都衍生自这个根种子。任何兼容HD钱包的根种子也可以重新创造整个HD钱包。

私有子密钥的衍生(子私钥)

分层确定性钱包使用CKD(child key dervation)方程去从母密钥衍生出子密钥

子密钥衍生方程是居于单向哈希方程。这个方程结合了:

  • 一个母私钥或者公钥(ECDSA未压缩键)
  • 一个叫链码(256 bits)的种子
  • 一个索引号(32bit)

链码是用来给这个过程引入看似的随机数据的,使得索引不能充分衍生其他的子密钥。因此有了子密钥,并不能让它发现自己的相似子密钥,除非有了链码。最初的链码种子(在链码树根部)是用随机数据构成的,随后链码从各子的母联码中衍生出来。

这三项相结合并散列可以生成子密钥。

母公钥---链码--以及索引号合并在一起使用HMAC-SHA512方程散列之后可以产生512位的散列。所得的散列可以被拆分为两部分。散列右半部分的256位产出可以给子链当链码。左半部分256位散列以及索引码被加载在母私钥上来衍生子私钥。

改变索引可以让我们延长母密钥以及创造序列中的其他子密钥。比如子0,子1,子2等。每一个母密钥可以有20亿个子密钥。

向密钥树下一层重复这个过程,每个子密钥可以依次称为母密钥继续创造它的子密钥,直到无限代。

使用衍生的子密钥

子私钥不能从非确定性(随机)密钥中被区分出来。因为衍生方程是单向方程,所以子密钥不能被用来发现他们的母密钥。子密钥也不能用来发现他们的相同层级的姊妹密钥。

只有母密钥以及链码才能得到所有的子密钥

子私钥可以用来做公共钥匙和比特币地址。之后它就可以被用那个地址来签署交易和支付任何东西。

子密钥、对应的公共钥匙以及比特币地址都不能从随机创造的密钥和地址中被区分出来。事实是它们所在的序列,在创造他们的HD钱包方程之外是不可见的。一旦被创造出来,它们就和“正常”钥匙一样运行了。

扩展密钥(扩展私钥、扩展公钥)

密钥衍生方程可以被用来创造密钥树上任何层级的子密钥。这只需要三个输入量:一个密钥、一个链码以及想要的子密钥的索引。

密钥+链码=extended key 可扩展密钥

扩展密钥可以简单地被存储并且表示为简单的将256位密钥与256位链码所并联的512位序列。

有两种扩展密钥:

扩展的私钥:私钥以及链码的结合。它可以被用来衍生子私钥(子私钥可以衍生子公钥);

扩展的公钥:公钥以及链码的结合。这个钥匙可以用来扩展公钥

想象一个扩展密钥作为HD钱包中钥匙树结构的一个分支的根。你可以衍生出这个分支的剩下所有部分。

扩展私钥可以创建一个完整的分支,而扩展公共钥匙只能够创造一个公钥的分支

一个扩展钥匙包括一个私钥(或者公钥)以及一个链码。

一个扩展密钥可以创造出子密钥并且能创再出在钥匙树结构中的整个分支。

扩展密钥通过Base58Check来编码,从而能轻易在不同BIP0032-兼容钱包之间导入导出。

扩展密钥编码用的Base58Check使用特殊的版本号,这导致在Base58编码字符中,出现前缀“xprv”和“xpub”。

这种前缀可以让编码更容易被识别。因为扩展密钥是512或513位,所以它比我们之前所看到的的Base58Check-encode串更长一些。

子公钥推导

分层确定性钱包的一个很有用的特点就是可以不通过私钥而直接从母公钥派生出子公钥的能力。

这样就有两种去衍生子公钥的方法:

  1. 通过子私钥;
  2. 直接通过母公钥。

因此,扩展的公钥可以在HD钱包结构的分支中,被用来衍生所有的公钥(且只有公钥)。

这种快捷方式可以用来创造非常保密的public-key-only配置。在配置中,服务器或者应用程序不管有没有私钥,都可以扩展公钥的副本。

这种配置可以创造出无限数量的公钥以及比特币地址。但是不可以花费送到这个地址里的任何比特币。

同时,在另一种更保险的服务器上,扩展私钥可以衍生出所有的对应的可签署交易以及花钱的私钥。

这种方案的一个常见方案是安装一个扩展的公钥在服务电商公共程序的网络服务器上。网络服务器可以使用这个公钥衍生方程去给每一笔交易(比如客户的购物车)创造一个新的比特币地址。但为了避免被偷,网络服务器不会有任何私钥。没有HD钱包的话,唯一的方法就是在不同的安全服务器上创造成千上万个比特币地址,之后就提前上传到电商服务器上。这种方法比较繁琐而且要求持续的维护来确保电商服务器不“用光”公钥。

这种解决方案的另一种常见应用就是冷藏或者硬件钱包。这种情况下,扩展的私钥可以被储存在纸质钱包中或者硬件设备中(比如Trezor硬件钱包),与此同时的扩展公钥可以在线保存。

使用者可以根据意愿创造“接收”地址,而私钥可以安全地在线下被保存,为了支付资金,使用者可以使用扩展的私钥离线签署比特币客户或者通过硬件钱包设备(比如Trezor)签署交易。

下图阐述了扩展母公钥来衍生子公钥的传递机制:

硬化子密钥的衍生

从扩展公钥衍生一个分支公钥的能力很重要,但有风险。

访问扩展公钥并不能得到访问子私钥的途径。但是,因为扩展公钥包含有(链码+公钥),如果子私钥被泄露,链码就可以被用来衍生所有其他子私钥。更糟的是,子私钥和母链码可以用来推导母私钥。

为了应对,HD钱包使用一种叫hardened derivation的替代衍生方程。这就“打破”了母公钥以及子链码之间的关系。

这个硬化衍生方程使用了母私钥去推导子链码,而不是母公钥。这就在母/子顺序中创造一道“防火墙”---有链码但是并不能用来推算子链码或者姊妹私钥。

强化的衍生方程看起来几乎与一般衍生的子私钥相同,不同的是子私钥被用来输入三联方程而不是母公钥。

当强化私钥衍生方程被使用时,得到的子私钥以及链码与使用一般衍生返程得到的结果完全不同。

得到的密钥“分支”可以被用来生产不易被攻击的扩展公钥。因为它所含的链码不能被用来开发或者暴露任何私钥。强化的衍生也被用来在上一层级,使用扩展公钥的密钥树中创造“间隙”。

简单讲,如果你想利用扩展公钥的便捷来衍生公钥的分支而不将自己暴露在泄露扩展链码的风险下,应该从强化母私链,而不是一般的母私链,来衍生公共钥匙。最好的方式是,为了避免推导出主钥匙,主钥匙所衍生的第一层级的子钥匙最好使用强化衍生。

正常衍生和强化衍生的索引号码

用在衍生方程中的索引号码是32位的整数。为了区分密钥是从正常衍生方程汇总衍生出来还是从强化衍生方程中产出。

这个索引号被分成两个范围:

0和2^31-1之间的是被用在常规衍生。

2^31和2^32-1之间的植被用在强化衍生方程。

为了让索引号码更容易被阅读和展示,强化子密钥的索引号码是从0开始了,但是右上角有一个小撇号。

第一个常规子密钥因此被表述为0,但是第一个强化子密钥(索引号为0x80000000)就被表示为0`。

第二个强化密钥依序有了索引号0x80000001,被显示为1'。

HD钱包密钥识别符(路径)

HD钱包中的密钥是用“路径”命名的。且每个级别之间用斜杆(/)字符来表示。

由主私钥生出的私钥起始以"m"打头。

因此,第一个母密钥生成的子私钥是m/0,第一个公钥是M/0。第一个子密钥的的子密钥是m/0/1。

密钥的“祖先”是从右向左读,直到你达到了衍生出的它的主密钥。

举例,标识符m/x/y/z描述的是子密钥m/x/y的第z个子密钥。而子密钥m/x/y又是m/x的第y个子密钥。m/x又是m的第x个子密钥。

HD钱包树状结构的导航

HD钱包树状结构提供了极大的灵活性。每一个母扩展密钥有40亿个子密钥:20亿个常规子密钥和20亿个强化子密钥。

而每个子密钥又会有40亿个子密钥并且以此类推。但是无穷代导致树状结构进行导航就变得异常困难。

两个比特币改进建议(BIPs)提供了这个复杂问题的解决办法----通过创建几个HD钱包树的提议标准。BIP0043提出使用第一个强化索引作为特殊的标识符表示树状结构的“purpose”。基于BIP0043, HD钱包应该使用且只用第一层级的数的分支,由索引号码去识别结构,并且由命名空间来定义剩余的树的目的地。

举例,HD钱包只使用分支m/i'/是为了表明那个被索引号i定义的特殊目地。

在BIP0043标准下,为了延长的那个特殊规范,BIP0044提议了多账户结构作为“purpose”。所有遵循BIP0044的HD钱包依据只使用数的第一个分支的要求而被定义:m/44'/。

BIP0044指定了包含5个预定义树状层级的结构:

m / purpose' / coin_type' / account ' / change / address_index

  • 第一层的目的地总是被设定为44'。
  • 第二层的“cion_type”特指密码货币硬币的种类并且允许多元货币HD钱包中的货币在第二个层级下有自己的亚树状结构。目前有三种货币被定义:Bitcoin is m/44'/0'、Bitcoin Testnet is m/44'/1'、Litecoin is m/44'/2'。
  • 第三层是“account”,可以允许使用者为了会计或者组织目的,而去再细分他们的钱包到独立的逻辑性亚账户。例如,一个HD钱包可能包含两个比特币“账户”:m/44'/0'/0'和m/44'/0'/1'。每个账户都是他自己亚树的根。
  • 第四层是“change”,每一个HD钱包有两个亚树,一个用来接收地址,一个是用来创造变更地址。无论先前的层级是否使用强化衍生,这一层级使用的都是常规衍生。这是为了允许这一层级的树可以在可供不安全环境下,输出扩展的公钥。
  • 第五层级的“address_index”,就是被HD钱包衍生的可用的地址的第四层级的子级。

高级密钥和地址

加密私钥(BIP0038)

私钥必须保密。

BIP0038提出了一个通用标准,使用一个口令加密私钥并使用Base58Check对加密私钥进行编码,这样加密的私钥就可以安全地保存在备份介质里,安全地在钱包间传输,保持密钥在任何可能被暴露情况下的安全性。这个加密标准使用了AES,这个标准由NIST建立,并广泛应用于商业和就是应用的数据加密。

BIP0038加密方案是:输入一个比特币私钥,通常使用WIF编码过,base58check字符串的前缀“5”。

此外BIP0038加密方案需要一个长密码作为口令,通常由多个单词或一段复杂的数字字母字符串组成。

BIP0038加密方案的结果是一个base58check编码过的加密私钥,前缀为6P。

许多钱包APP现在能够识别BIP0038加密过的私钥,会要求用户提供口令解码并导入密钥。第三方APP,诸如基于浏览器的Bit Address,可以被用来解码BIP0038的密钥。

最通常使用BIP0038加密的密钥用例是纸钱包---一张纸张上备份密钥。只要用户选择了强口令,使用BIP0038加密的私钥纸钱包就无比的安全,是一种很棒的线下比特币存储途径(也被称作“冷库”)。

例子:

P2SH(Pay-to-Script Hash)和多签名地址

传统的比特币地址从数字1开头,来源于公钥,而公钥来源于私钥。

虽然任何人都可以讲比特币发送到一个1开头的地址,但比特币只能在通过相应的私钥签名和公钥哈希值后才能消费。

以数字3开头的比特币地址是P2SH地址,有时候被错误的称为“多重签名”或“多重签名地址”。他们指定比特币交易中受益人作为哈希的脚本,而不是公钥的所有者。

这个特性在2012年1月由BIP0016引进,目前因为BIP0016提供了增加功能到地址本身的机会而被广泛采纳。不同于发送资金到传统1开头的比特币地址交易(P2PKH),资金被发送到3开头的地址时,不仅仅需要一个公钥的哈希值,同时也需要一个私钥签名作为所有者证明。在创建地址的时候,这些要求会被定义在脚本中,所有对地址的输入都会被这些要求阻隔。

一个P2SH地址从事务脚本中创建,它定义谁能消费这个事务输出。编码一个P2SH地址涉及使用一个在创建比特币地址用到过的双重哈希函数,并且只能应用在脚本而不是公钥:

script hash = RIPEMD168(SHA256(script))

脚本哈希的结果是由Base58Check编码前缀为5的版本、编号后等到开头为3的编码地址。

P2SH不一定是多重签名的交易。虽然P2SH地址通常都是代表多重签名,但也可能是其他类型的交易脚本。

多重签名地址和P2SH

目前,P2SH函数最常见的实现时用于多重签名地址脚本。

底层脚本需要多个签名来证明所有权,此后才能消费资金。设计比特币多重签名特性是需要从总共N个密钥中需要M个签名(“阈值”),被称为M-的-N的多签名,其中M是等于或小于N。

例如,咖啡店主鲍勃使用多重签名地址需要1-2签名,一个是属于他的密钥和一个属于他同伴的密钥,以确保其中一方可以签署过一阁书屋锁定输出到这个地址。这类似于银行的“联合账户”,其中任何一方配偶可以凭借单一签名消费。

比特币靓号地址

靓号地址包含了可读信息的有效比特币地址。

靓号地址需要生成并通过数十亿的候选私钥测试,直到一个私钥能生成具有所需图案的比特币地址。

生成靓号地址是一项通过蛮力的过程。

纸钱包

纸钱包是打印在纸张上的比特币私钥。纸钱包顾名思义就是把比特币地址和私匙记录到一张“纸”上面,不过这张纸即可以打印出来也可以存放到网络里面。

通过使用工具,就可以人容易生成纸钱包。

譬如bitaddress.org网站上的客户端Javascript生成器。这个页面包含所有必要的代码,甚至在完全失去网络连接的情况下,也可以生成密钥和纸钱包。

猜你喜欢

转载自blog.csdn.net/sinat_37138973/article/details/111514928