用NBitcoin进行区块链开发(7):助记词

2019-03-07 17:24:23 浏览数 (1)

比特币的私钥是256位的二进制数字,占32个字节,比如: 3243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C8

这串数字输入费劲,还容易出错,中本聪就规定了一种WIF格式,称为Wallet Import Format,这种格式的私钥可以非常方便地导入到Bitcoin Core等钱包软件中。

刚才的私钥转换为WIF格式,以字母K开头: KxuRLWqnfcgs8ru7YiMBfP6T71jK9twCedaeBtHgRgzb8adnoZzH

管理一大堆私钥仍然非常麻烦,BIP32规范引入了HD钱包的概念,这里的HD不是HardDisk的缩写,而是指分层确定性(Hierarchical Deterministic)钱包。

有了HD钱包,只需备份好一个主私钥就可以生成所有其它私钥,所以私钥的备份显得尤为重要,抄错一个字母,可能币就丢了,因此BIP39规范又引入了助记词mnemonic words。

助记词由12个到24个常用单词组成,比如:

base quality head cereal media bracket castle either sign crumble pull rug

NBitcoin中提供了一个Mnemonic类,可以方便生成助记词,也可以通过助记词生成私钥。

代码语言:javascript复制
Mnemonic m = new Mnemonic(Wordlist.English, WordCount.Twelve);
Console.WriteLine(string.Join(" ", m.Words));
m = new Mnemonic(Wordlist.English, WordCount.Eighteen);
Console.WriteLine(string.Join(" ", m.Words));
m = new Mnemonic(Wordlist.English, WordCount.TwentyFour);
Console.WriteLine(string.Join(" ", m.Words));
输出结果
method bachelor promote into sense autumn bag stock genuine style canyon warm
pair move hire skirt acquire wreck repeat motion actual brown kid today virus mansion portion demise possible brother
hamster museum voyage unveil chuckle grit inform clog ripple blur rug entry fruit saddle you undo drama home business company dinner cupboard unfold lawsuit

有了主私钥之后,与不同的KeyPath结合,可以扩展出多币种、多帐户的不同地址,理论上可以是无穷多个。

图片摘自《精通比特币》

BIP44规范中又对KeyPath的5个组成部分进行了明确约定:

m / purpose’ / coin_type’ / account’ / change / address_index

purpose在BIP44中设置为常量44。

coin_type标识币种,BTC是0,以太坊是60,BCH是145,EOS是194,XMR是128。详细列表见这个网址: https://github.com/satoshilabs/slips/blob/master/slip-0044.md

account可以指定不同的帐户,比如用于捐赠的,用于挖矿的,用于消费的等等,根据个人喜好设置。

change用于生成找零地址。

最后的index还可以指定多个地址。

根据这种定义,第一个BTC地址的KeyPath就是:

m/44’/0’/0’/0/0

m表示私钥。M表示公钥。 值得注意的是里面的单撇符号,前3个数字后面有单撇,后面2个数字则没有。单撇的含义是hardened,相当于安全加固,用于切断某些子私钥的相关性,避免泄漏了某个子私钥对其它私钥造成影响。

而下一个BTC地址的KeyPath则是:

m/44’/0’/0’/0/1

很多种钱包都遵守BIP44规范:

  • Mycelium Bitcoin Wallet
  • TREZOR (source)
  • KeepKey (source)
  • Ledger Wallet (source)
  • Jaxx

在NBitcoin中可以方便地计算出这些私钥和地址:

代码语言:javascript复制
string strWords = "base quality head cereal media bracket castle either sign crumble pull rug";
Mnemonic mm = new Mnemonic(strWords, Wordlist.English);
ExtKey hdroot = mm.DeriveExtKey();

// the first BTC address
var extkey = hdroot.Derive(new KeyPath("m/44'/0'/0'/0/0"));
var btcPriv1 = extkey.PrivateKey.GetWif(Network.Main);
Console.WriteLine(btcPriv1);
var btcAddr1 = btcPriv1.GetAddress();
Console.WriteLine(btcAddr1);

// the second BTC address
extkey = hdroot.Derive(new KeyPath("m/44'/0'/0'/0/1"));
var btcPriv2 = extkey.PrivateKey.GetWif(Network.Main);
Console.WriteLine(btcPriv2);
var btcAddr2 = btcPriv2.GetAddress();
Console.WriteLine(btcAddr2);

在下面这个网站中可以非常方便地验证上面代码的正确性: https://iancoleman.io/bip39/#english

上面程序输出的私钥和地址:

代码语言:javascript复制
L39FE7LfN5wBfLJthraKVhCdgDaWFgNn5xWhUgzfamWuzitbsjma
1DHQZkmhKSEEjzfP9cAFfKABeVivTpXJwq
Kwgo2fdv2mjQfMmBarMqLfCigwRdALeq9ek38wETMuevb9TaXGJp
1AJjN85VyZSffPDaFzfeyeTV5shNdUGpCg

你也可以将上面的12个助记词导入到Jaxx钱包中,看看生成的BTC、BCH、ETH等地址是否完全一致。不怕麻烦的话,也可以自己生成一套助记词,恢复到Ledger Nano S硬件钱包中。

Jaxx钱包显示私钥的结果

ETH的私钥和地址的编码方式与BTC的不一样,在NBitcoin中当然无法显示以太坊的东西,需要使用Nethereum的类库,请自行从nuget里安装即可。

代码语言:javascript复制
extkey = hdroot.Derive(new KeyPath("m/44'/60'/0'/0/0"));
var eth1 = new Nethereum.Signer.EthECKey(extkey.PrivateKey.ToBytes(), true);
Console.WriteLine(eth1.GetPrivateKey());
Console.WriteLine(eth1.GetPublicAddress());

extkey = hdroot.Derive(new KeyPath("m/44'/60'/0'/0/1"));
var eth2 = new Nethereum.Signer.EthECKey(extkey.PrivateKey.ToBytes(), true);
Console.WriteLine(eth2.GetPrivateKey());
Console.WriteLine(eth2.GetPublicAddress());

对应的私钥和地址:

代码语言:javascript复制
0x00daa97f89afd2a06279cdfc3c5f488f97b2bb89bc4af95882cac8065704c74fdf
0x4ffc6A9E3CfF2D670f02a1dC7b8aaAF705FEBFfb
0x0088cd6fa7ab95499ed3f8271ac7bc8495e9372fb540098a6c85a9ad7d89d3d43a
0x87c6d9ab2d28c870ECeB9c8e34236Add80874B2d

掌握了这些私钥和地址的生成规则后,请自行练习生成BCH和BSV的私钥和地址。

0 人点赞