比特币钱包波及钱包程序和钱包文件。钱包程序创立公钥来承受比特币(satoshis)付款,并应用对应的私钥来花掉比特币。钱包文件保留私钥和其余与钱包程序相干的交易信息(可选)。

钱包程序 Wallet Programs

容许承受和领取比特币是钱包软件的惟一性能,然而一个特定的钱包程序不须要同时做这两件事,两个钱包程序能够一起工作,一个程序散发公钥来接管比特币,一个程序进行交易签名来领取这些比特币。

钱包程序也须要和peer-to-peer网络进行交互,以从区块链中取得信息并播送出新的交易。当然,散发公钥和交易签名程序并不需要和peer-to-peer网络自身进行交互。

因而钱包零碎(wallet system)就有三个必须的,然而缺能够独立的局部:一个公钥散发程序,一个签名程序,一个联网程序。

<!--more-->

NOTE: 这里说的是公钥散发的通常情景。在一些状况下,P2PKH和P2SH的散列值将被散发来代替公钥的散发,理论的公钥只有在他们管制的output被领取时才散发。
下面和上面说的输入outputs,通常就是指 未应用的交易输入 unspent transaction outputs 缩写是UTXO,就是比特币。

残缺性能的钱包 Full-Service Wallets

最简略的钱包是一个执行三个性能的程序:

  • 生成私钥,并派生对应的公钥,并在须要时候发这些公钥;
  • 监控领取给这个公钥的outputs,在领取outputs时,创立交易和进行交易签名;
  • 播送曾经实现签名的交易。

当初简直所有风行的BTC钱包都是Full-Service Wallets

Full-Service Wallets的长处是容易应用,独自的一个程序能够实现用户领取和接管比特币的全副工作。

Full-Service Wallets的毛病是,他们把私钥保留在能够连贯到Internet的设施上,因为联网所以这样的设施中的私钥被攻打会很容易。

签名钱包 Signing-Only Wallets

私钥能够保留在一个在更平安环境中的独自的钱包程序中来进步安全性,这些签名钱包和能够与peer-to-peer网络交互的联网钱包配合应用。

签名钱包通常由确定性密钥(deterministic key)创立,用来创立能够生成子公私钥的父公私钥。

当第一次运行时,签名钱包创立一个父私钥,并将对应的公钥传输给联网钱包。

联网钱包应用父公钥派生出子公钥,帮忙散发他们(可选的),监控领取给这些公钥的outputs,创立没有签名的领取交易,并把没有签名的领取交易传输给签名钱包。

通常用户有机会应用签名钱包查看未签名交易的详情(尤其是outputs的详情)。

在用户查看步骤(可选的)之后,签名钱包应用父私钥派生相应的子私钥并进行交易签名,将签名的交易传回给联网钱包。

联网钱包把签名的交易播送到peer-to-peer网络上。

离线钱包 Offline Wallets

几个full-service wallets也能够当作两个独立的钱包应用:一个程序实例当作签名钱包(通常称为“离线钱包”),另一个程序实例当作联网钱包(通常称作在线钱包或者监控钱包)。

脱机钱包在不联网的设施上运行,能够缩小供给量。如果这种状况,通常由用户来把握所有数据的传输和应用可挪动设施比方USB驱动器。用户的工作流是这样的:

  • 1.(离线)敞开设施上所有网络连接,并装置钱包软件。以脱机模式启动软件,创立父私钥和父公钥,并赋值父公钥到可挪动介质上。
  • 2.(在线)在另一台设施上装置钱包软件。这台设施联网,从可挪动介质上导入父公钥。上面的过程就像应用full-service wallet一样,散发公钥来接管领取。当筹备生产比特币时,填写output详情并把钱包生成的未签名的交易保留到可挪动介质上。
  • 3.(离线)在脱机实例中关上未签名的交易,审查交易的详情,确保领取金额和地址正确。这个能够阻止恶意软件(malware)坑骗用户签订交易,从而领取给攻击者。审查后,签订交易并保留到可挪动介质。
  • 4.(在线)在在线实例中关上已签名的交易,以便播送到peer-to-peer网络。

离线钱包的次要长处在于同残缺性能的钱包相比,大大的提告了安全性。只有脱机钱包没有被毁坏(或者有缺点),用户在签名之前会查看所有领取的交易,即便在线钱包被毁坏,用户的比特币也是平安的。

离线钱包的次要毛病是麻烦,为了最大的安全性,要求用户必须离线操作。任何时候要领取比特币,都必须启动离线设施,用户必须从在线设施物理拷贝数据到离线设施并再从离线设施拷贝数据回在线设施。

硬件钱包 Hardware Wallets

硬件钱包是专门用于签名的钱包设施,个别是智能卡等平安芯片开发的设施。他们能够平安与其余联网设施通信,用户也不须要手动传输数据了。硬件钱包的工作流程是这样的:

  • (硬件)生成父私钥和公钥,将硬件钱包连贯到一个联网设施上,这样联网设施就能够取得父公钥;
  • (联网)像应用残缺性能钱包一样,散发公钥来接管领取,当筹备领取比特币时,填写交易详情,连贯硬件钱包,而后点击生产,联网钱包会将交易详情发送给硬件钱包;
  • (硬件)查看硬件钱包屏幕上的交易详情,一些硬件钱包可能会提醒输出PIN,硬件钱包对交易进行签名,并将交易签名返回给联网钱包。

散发钱包 Distributing-Only Wallets

运行再很难保障平安的环境中(比方web服务器)的钱包程序,只能设计成分发公钥而不能有其余性能。这种简略的钱包有两种常见的设计办法:

  • 把大量的公钥或者地址保留到数据库中,而后依据申请散发一条数据库内的条目比方一个公钥或者地址。为了防止重复使用密钥,web服务器应该追踪应用过的密钥,并且永远不要用尽数据库中的公钥。
  • 应用父公钥创立子公钥。为了防止重复使用密钥,必须应用一种办法确保一个公钥不会被散发两次。

这两种办法都不会减少大量的开销。

钱包文件 Wallet Files

比特币钱包的外围是一组私钥。这些汇合被数字化的保留在一个文件中,甚至能够保留在一张纸上。

私钥格局 Private Key Formats

私钥是用来解锁对应公钥地址的比特币的。在比特币中,规范格局的私钥是一个256bit的数字,值在下列范畴内:

0x01 ~ 0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4140

这个范畴是由比特币应用的secp256k1 ECDSA加密规范治理。

钱包导入格局 Wallet Import Format(WIF)

为了使得私钥复制不容易出错,能够应用钱包导入格局WIF。WIF应用base58Check对私钥进行编码,大大的升高了复制出错的机会,就像规范比特币地址一样。

  • 1.应用一个私钥
  • 2.在后面增加一个0x80作为mainnet地址,或者增加一个0xEF作为testnet地址;
  • 3.如果他应该和压缩公钥一起应用,在前面追加一个0x01.如果与未压缩的公钥一起应用,则不会追加任何数据。
  • 4.对扩大后的密钥进行SHA-256哈希;
  • 5.对SHA-256的后果进行SHA-256哈希;
  • 6.取第二个哈希后果的前4字节作为校验和;
  • 7.把从第5布取得的校验和增加到第2步扩大密钥的开端;
  • 8.应用Base58Check编码把第7步的数据转换未Base58字符串。

迷你私钥格局 Mini Private Key Format

迷你私钥格局是一种将私钥编码到30个字符以内的办法,能够将密钥嵌入到较小的物理空间中,比方物理比特币Token,或者QR Code中。

  • 1.迷你密钥的第一个字符是‘S’;
  • 2.为了确定私钥格局良好,再私钥上增加一个问号;
  • 3.计算SHA256哈希,如果产生的第一个字节是‘00’,他是格局良好的。密钥的限度规定是一种输出查看typo-checking办法,用户应用应用随机数生成密钥,直到生成格局良好的密钥;
  • 4.为了生成残缺私钥,用户只须要获取原始迷你私钥的单个SHA256哈希值。这个过程是单向的,很难从生成密钥计算出迷你私钥格局;
  • 5.在很多实现中不容许字符‘1’呈现在迷你私钥中,因为它与‘l’在视觉上类似;

    下面写的很顺当,我回头再整顿一下,从新写一下。

    ## 公钥格局 Public Key Formats

    比特币的ECDSA公钥示意特定椭圆曲线上的一个点,比特币应用的是secp256k1。再传统的未压缩模式中,公钥蕴含identification byte,一个32 bytes的X坐标,一个32 bytes的Y坐标。

上面一个超级简略的图示意比特币应用的椭圆曲线上的一个点,$y^2= x^3+7$

沿着曲线只有两个点共享任何X坐标,所以只须要一个bit来示意Y坐标的正负即可,也就是把Y坐标压缩成1bit,这样就在不扭转任何内容的状况下,实现了靠近50%的公钥压缩

应用这个压缩公钥不会失落数据,只须要应用大量运算就能够重建Y坐标并应用未压缩的公钥。在secp256官网文档中形容了未压缩和压缩的公钥,宽泛应用的明码算法库个别都反对这两种格局公钥。

因为容易应用,他们缩小了区块链的空间,压缩的公钥是比特币内核Bitcoin Core的默认值,也是所有比特币软件的举荐默认值。

Bitcoin Core在0.6之前的版本,应用了未压缩密钥。这个造成一些复杂性。未压缩的密钥和压缩的密钥哈希模式不同。所以同一个密钥实用两个不同的P2PKH地址。这也就意味着在签名脚本中密钥必须以正确的格局提交,以便与后面输入的公钥脚本中的哈希值匹配。

因为这个起因,Bitcoin Core应用了几个不同的identifier byte来帮忙程序辨认密钥应该如何应用:

  • 与压缩公钥一起应用的私钥在Base58编码之前附加了0x01;
  • 未压缩的公钥以0x04结尾;压缩的公钥0x03或者0x02结尾,这个前缀也在secp256k1
    官网文档中应用。

分层确定性密钥创立 Hierarchical Deterministic Key Creation

晚期的比特币客户端中钱包都是随机生成的私钥汇合,这些密钥都须要用户本人保留正本,如果一旦密钥失落,那么对应的钱包就不能拜访,钱包管制的比特币也就无奈应用了。比特币有一个防止地址重复使用的准则,每个比特币地址只能一次交易,这样用户就会有大量的私钥要进行保留和备份,所以晚期计划不是一个好的方法。

分层确定性密钥和传输协定大大简化了钱包备份,打消了应用同一个钱包的多个程序之间反复通信的须要,容许创立能够独立操作的子账户,赋予每个父账户监控或者管制其子账户的能力,即便子账户受到破坏,每个账户分为齐全拜访和限度拜访两局部,这样不受信赖的用户就或者程序就能够接管或者监控领取,然而不能对外领取。

HD协定利用了ECDSA公钥创立函数-point(),它去一个大数(私钥),并将其转换为曲线上的的点(公钥):

point(private_key) == public_key

因为point()的工作形式,它让通过组合一个曾经存在的公钥(父公钥)和另一个公钥(通过一个integer(i)值)来创立子公钥成为可能。p是一个所有比特币软件都应用的全局常量

point( (parent_private_key + i) % p ) == parent_public_key + point(i)

这就意味着两个或者多个独立的程序,如果对一个整数序列达成统一,就能够从繁多的父密钥对创立一系列惟一的子密钥对,而不须要进行额定的通信。此外,为收款散发新的公钥,程序能够在不接触私钥的状况实现,从而容许公钥散发程序在一个不平安的环境(web服务器)上运行。

子公钥也能够通过重复子密钥扩散操作来创立他们本人的子公钥(孙公钥):

point( (child_private_key + i) % p ) == child_public_key + point(i)

是否创立子公钥或者更后辈的公钥,对于所有交易来说,应用一个可预测的整数序列不会比应用繁多公钥好,因为任何人晓得一个子公钥能够找到所有其余的通过这个父公钥扩散的子公钥。相同的,应用一个随机种子来确定生成的整数序列,这样没有种子的人无奈看到子公钥之间的关系。

HD协定应用一个繁多的根种子和无关联的确定代际(unlinkable deterministically-generated)的整数来创立子代,孙子代和其余更后辈的密钥。每个子密钥也通过它的父代取得一个代际(deterministically-generated)种子,称为链代码(chain code),所以一个chain code受到破坏,不会毁坏整个序列的层次结构。

HD密钥扩散须要四个输出:

  • 父私钥和父公钥,惯例的未压缩256 bits的ECDSA密钥;
  • 父chain code是256 bits看起来随机的数据;
  • 索引index是程序指定的32-bit整数。

在上图所示的规范模式中,父chain code、父公钥和索引index被输出到单向哈希HMAC-SHA512中,生成确定代际然而看起来随机(determistically-generated-but-seemingly-random)的512 bits数据。哈希输入总共512 bits,左边的256 bits(低256 bits)数据被用来作为新的子chain code。哈希输入的右边256 bits被当作一个整数和父私钥或者父公钥组合(父私钥和哈希输入的高256bits椭圆曲线上做加法模G运算),来创立子私钥或者子公钥:

child_private_key == (parent_private_key + lefthand_hash_output) % Gchild_public_key == point( (parent_private_key + lefthand_hash_output) % G )child_public_key == point(child_private_key) == parent_public_key + point(lefthand_hash_output)

父chain code、父公钥、索引index计算HMAC-SHA512的过程如下:父公钥(256bits)和子密钥的index(32bits)进行拼接,公钥在高位索引在位置,合并后的字节序是大端,对合并后的数据进行HMAC-SHA512运算,父chain code作为哈希密钥。

能够看进去,父私钥和对应代际的chain code能够算出子私钥,而后用point()和子私钥能够算出子公钥,还能够用子公钥和point(父chain code)算出子公钥,这样也能够在不须要私钥的状况下,只晓得某一代际的公钥和对应代际的chain code就能够算出下一代的公钥。

指定不同的代际索引index,能够应用雷同的父密钥扩散出不同的无关联的子密钥。子密钥应用子chain code反复密钥扩散过程能够生成无关联的孙密钥。

因为创立子密钥须要密钥和chain code两者,密钥和chain code合在一起被称作扩大密钥。一个扩大私钥和对应的扩大公钥具备雷同的chain code。 主私钥(最顶层)和主chain code是由随机数生成。

根种子(root seed)是由123 bits、256 bits或者512 bits的随机数生成的。这个根种子,起码128 bits是须要用户备份的惟一数据,未来用于通过特定的钱包和设置来扩散所有的密钥。

根种子通过哈希来创立512 bits看起来随机的数据,通过这些数据来创立主私钥和主chain code(合在一起称作主扩大密钥)。主公钥通过主私钥应用point()计算得出,主公钥和主chain code合在一起称作主扩大公钥。主扩大密钥和其余扩大密钥在性能上等效,只是因为它位于最上层的地位,所以才显得不同。

根种子的哈希后512 bits的输入,右边256 bits作为主私钥,左边256bits作为主chain code

强化密钥 Hardened Keys

强化扩大密钥(Hardened extended keys)修复了一般扩大密钥的一个潜在问题。如果攻击者取得了一个一般扩大密钥的父chain code和父公钥,他就能够暴力取得所有的通过这个chain code派生进去的chain code。如果攻击者还取得了一个子私钥、孙子私钥或者更下一代的私钥,他就能够应用chain code生成这个私钥后辈所有的私钥了。

更蹩脚的是,攻击者能够逆向(reverse)一般的子私钥扩散公式,只有从子私钥中减去父chain code就能够复原父私钥,如上图子代和父代所示。这意味着一个攻击者,只有取得了一个扩大公钥和及其后辈的任何私钥,就能够复原出改公钥的私钥及其扩散出的所有密钥。

因为扩大公钥中有对应层级的chain code,所以能够失去这个公钥后辈任意代际的公钥,所以只有取得了这个公钥后辈的私钥,就能够算到这个私钥上一代的chain code,而后通过私钥-chain code计算出上一代私钥,最初推算出这个公钥和后辈的所有密钥。

下面的强化公示将索引index、父chain code和父私钥组合在一起用来创立产生子chain code和子私钥的数据。这个公示让在不晓得父私钥的状况下不能创立子公钥。换句话说,父扩大公钥不能创立强化子公钥。

强化密钥生成过程,在父私钥后面补一个0x00字节,父私钥和索引index拼接,私钥在高位,索引在低位,字节序为大端。对拼接后的数据进行HMAC-SHA512运算,哈希密钥是父chain code,父私钥和哈希的高256 bits做椭圆曲线上的加法模运算生成子私钥,低256 bits是子chain code。如果ECC模运算后果呈现0,那么索引值递增,而后再次计算密钥。子公钥能够通过子私钥计算出来。

因而,强化扩大私钥没有一般的扩大私钥有用,然而强化扩大私钥会创立一个防火墙,使得多层密钥扩散泄露不会产生。因为强化子扩大公钥无奈仅仅靠本人生成孙chain code,父扩大公钥的泄露不能和孙私钥的泄露组合创立重孙扩大私钥。

HD协定应用不同的索引index来批示是生成一般还是强化密钥。索引Index从0x00~0x7FFFFFFF将生成一般密钥;索引Index从0x80000000~0xFFFFFFFF将生成强化密钥。为了便于形容,许多开发者应用'(prime symbol)来示意强化密钥,所以第一个一般密钥(0x00)是0,第一个强化密钥(0x80000000)是0'。

(比特币的开发者通常应用ASCII的撇号,而不是应用unicode的prime symbol。)

这个压缩形容进一步联合斜杠和m或者M前缀,批示档次(hierarchy)和密钥类型。m示意私钥,M示意公钥。例如,m/0'/0/122'示意主私钥的第1代(index=0)强化子密钥的第1代(index=0)一般子密钥的第123代(index=122)强化子私钥(通过索引index)。

恪守BIP32 HD协定的钱包只创立主私钥(m)的强化子密钥来避免子密钥泄露而导致主密钥泄露。因为主密钥不存在一般子密钥,所以主公钥也不会在HD钱包里应用。所有其余密钥能够有一般子密钥,所以能够应用对应的一般扩大公钥。

HD协定还形容了扩大公钥和扩大私钥的序列化格局。详细情况能够参看BIP32协定。

保留根种子 Storing Root Seeds

HD协定里的根种子(root seeds)是128、256或者512 bits的随机数,这些种子须要备份保留。为了不便,能够应用非数字化备份的办法,比方记忆、手抄等。BIP39定义了一个办法,通过助记符来创立512 bits的根种子。

生成单词数与应用的熵值相干:

Entropy BitsWords
12812
16015
19218
22421
25624

明码短语(passphrase)能够是任意长度,它能够简略得追加到助记符pseudo-sentence,mnemonic和password将应用2048次HMAC-SHA512运算,产生一个看起来随机的512 bits种子。

涣散密钥钱包 Loose-Key Wallets

涣散密钥钱包仿佛中文也有叫零型非确定钱包,也被称作Just a Bunch Of Keys(JBOK),是一种Bitcoin Core客户端晚期的钱包模式,曾经被弃用。Bitcoin Core客户端钱包通过伪随机数发生器主动创立100个公私钥对供当前应用。

这些没有应用的私钥存储在一个虚构的密钥池(key pool)中,之前生成的密钥被应用后,就会生成新的密钥放到池中,保障池中有100个未应用的密钥。