【密钥、地址、钱包】
私钥是一个256位的二进制数据。私钥随机产生,所以任何2人的私钥存在重复的可能。
以下是⼀个随机⽣成的私钥(k),以⼗六进制格式表⽰(256位的⼆进制数,以64位⼗六进制数显⽰,每个⼗六进制数占4位):
getnewaddress 命令。出于安全考虑,命令运⾏后只显⽰⽣成的公钥,⽽不显⽰私钥。如果要bitcoind显⽰私钥,可以使⽤ dumpprivkey 命令。
dumpprivkey 命令会把私钥以Base58校验和编码格式显⽰,这种私钥格式被称为钱包导⼊格式(WIF,Wallet Import Format).
WIF:Wallet Import Format.
公钥K 被定义为⼀个点 K = (x, y):
由公钥(⼀个同样由数字和字⺟组成的字符串)⽣成的⽐特币地址以数字“1”开头。下⾯是⼀个⽐特币地址的例⼦:
以公钥 K 为输⼊,计算其SHA256哈希值,并以此结果计算RIPEMD160 哈希值,得到⼀个⻓度为160⽐特(20字节)的数字,K是公钥,A是⽣成的⽐特币地址。
通常⽤⼾⻅到的⽐特币地址是经过“Base58Check”编码的。
Base64使⽤了26个⼩写字⺟、26个⼤写字⺟、10个数字以及两个符号(例如“+”和“/”),⽤于在电⼦邮件这样的基于⽂本的媒介中传输⼆进制数据。Base64通常⽤于编码邮件中的附件。
Base58不含Base64中的0(数字0)、O(⼤写字⺟o)、l(⼩写字⺟L)、I(⼤写字⺟i),以及“+”和“/”两个字符。简⽽⾔之,Base58就是由不包括(0,O,l,I)的⼤⼩写字⺟和数字组成。
Base58Check是⼀种常⽤在⽐特币中的Base58编码格式,增加了错误校验码来检查数据在转录中出现的错误。校验码⻓4个字节,添加到需要编码的数据之后。校验码是从需要编码的数据的哈希值中得到的,所以可以⽤来检测并避免转录和输⼊中产⽣的错误。使⽤Base58check编码格式时,编码软件会计算原始数据的校验码并和结果数据中⾃带的校验码进⾏对⽐。⼆者不匹配则表明有错误产⽣,那么这个Base58Check格式的数据就是⽆效的。例如,⼀个错误⽐特币地址就不会被钱包认为是有效的地址,否则这种错误会造成资⾦的丢失。
为了使⽤Base58Check编码格式对数据(数字)进⾏编码,⾸先我们要对数据添加⼀个称作“版本字节”的前缀,这个前缀⽤来明确需要编码的数据的类型。例如,⽐特币地址的前缀是0(⼗六进制是0x00),⽽对私钥编码时前缀是128(⼗六进制是0x80)。
Base58Check编码的⽐特币地址是以1开头的,⽽Base58Check编码的私钥WIF是以5开头的。表4-1展⽰了⼀些版本前缀和他们对应的Base58格式。
【密钥】
Base58Check WIF 私钥:
Base58Check WIF-compressed 私钥:
【公钥格式】
未压缩格式公钥使⽤04作为前缀,⽽压缩格式公钥是以02或03作为前缀。
如果我们使⽤双哈希函数(RIPEMD160(SHA256(K)))将压缩格式公钥转化成⽐特币地址,得到的地址将会不同于由⾮压缩格式公钥产⽣的地址。这种结果会让⼈迷惑,因为⼀个私钥可以⽣成两种不同格式的公钥——压缩格式和⾮压缩格式,⽽这两种格式的公钥可以⽣成两个不同的⽐特币地址。但是,这两个不同的⽐特币地址的私钥是⼀样的。
“压缩格式私钥”是⼀种名称上的误导,因为当⼀个私钥被使⽤WIF压缩格式导出时,不但没有压缩,⽽且⽐“⾮压缩格式”私钥⻓出⼀个字节。这个多出来的⼀个字节是私钥被加了后缀01,⽤以表明该私钥是来⾃于⼀个较新的钱包,只能被⽤来⽣成压缩的公钥。
【助记码】
确定性种子钱包:熵 -> 助词码 -> 钱包。
BIP0039定义助记码和种⼦的创建过程如下:
1.创造⼀个128到256位的随机顺序(熵)。
2.提出SHA256哈希前⼏位,就可以创造⼀个随机序列的校验和。
3.把校验和加在随机顺序的后⾯。
4.把顺序分解成11位的不同集合,并⽤这些集合去和⼀个预先已经定义的2048个单词字典做对应。
5.⽣成⼀个12⾄24个词的助记码。
【钱包】
分层确定性钱包(HD Wallet):
根种⼦输⼊到HMAC-SHA512算法中就可以得到⼀个可⽤来创造master private key(m) 和 a master chain code的哈希。主私钥(m)之后可以通过使⽤我们在本章先前看到的那个普通椭圆曲线 m * G 过程⽣来成相对应的主公钥(M)。链代码可以给从⺟密钥中创造⼦密钥的那个⽅程中引⼊的熵。
每⼀个⺟密钥可以右20亿个⼦密钥。
母公共钥匙——链码——以及索引号合并在一起并且用HMAC-SHA512方程散列之后可以产生512位的散列。所得的散列可被拆分为两部分。散列右半部分的256位产出可以给子链当链码。左半部分256位散列以及索引码被加载在母私钥上来衍生子私钥。
密钥以及链码这两个重要的部分被结合之后,就叫做 extended key。术语“extended key”也被认为是“可扩展的密钥”是因为这种密钥可以⽤来衍⽣⼦密钥。扩展私⼈钥匙可以创建⼀个完整的分⽀⽽扩展公共钥匙只能够创造⼀个公共钥匙的分⽀。
在Base58Check编码中,扩展私钥以xprv开关,而扩展公钥以xpub开头。
这是⼀个在Base58Check中编码的扩展私钥的例⼦:
这是在Base58Check中编码的对应的扩展公共钥匙:
【硬化子秘钥衍生】
HD钱包使用一种叫做 hardened derivation 的替代衍生方程。这就“打破”了母公共钥匙以及子链码之间的关系。这个硬化衍生方程使用了母私钥去推到子链码,而不是母公共钥匙。
强化衍生避免了子链编码的泄露。
⽤在衍⽣⽅程中的索引号码是32位的整数。为了区分密钥是从正常衍⽣⽅程中衍⽣出来还是从强化衍⽣⽅程中产出,这个索引号被分为两个范围。
索引号在0和231–1(0x0 to 0x7FFFFFFF)之间的是只被⽤在常规衍⽣。
索引号在231和232–1(0x80000000 to 0xFFFFFFFF)之间的只被⽤在强化衍⽣⽅程。
因此,索引号⼩于2^31就意味着⼦密钥是常规的,⽽⼤于或者等于2^31的⼦密钥就是强化型的。
为了让索引号码更容易被阅读和展⽰,强化⼦密码的索引号码是从0开始展⽰的,但是右上⻆有⼀个⼩撇号。
第⼀个常规⼦密钥因此被表述为0,但是第⼀个强化⼦密钥(索引号为0x80000000)就被表⽰为0'。
第⼆个强化密钥依序有了索引号0x80000001,且被显⽰为1',以此类推。当你看到HD钱包索引号i',这就意味着 231+i。
【HD钱包密钥标识符】
BIP0038加密⽅案的结果是⼀个由base58check编码过的加密私钥,前缀为6P。如果你看到⼀个6P开头的的密钥,这就意味着该密钥是被加密过,并需要⼀个⼝令来转换(解码)该密钥回到可被⽤在任何钱包WIF格式的私钥(前缀为5)。
【P2SH】
Pay-to-Script Hash。以数字3开头的⽐特币地址是P2SH地址,有时被错误的称谓多重签名或多重签名地址。
不同于P2PKH交易发送资⾦到传统1开头的⽐特币地址,资⾦被发送到3开头的地址时,需要的不仅仅是⼀个公钥的哈希值,同时也需要⼀个私钥签名作为所有者证明。
P2SH函数最常⻅的实现是⽤于多重签名地址脚本。顾名思义,底层脚本需要多个签名来证明所有权,此后才能消费资⾦。设计⽐特币多重签名特性是需要从总共N个密钥中需要M个签名(也被称为“阈值”),被称为M-N多签名,其中M是等于或⼩于N。