參考[https://blog.csdn.net/qq_16137795/article/details/84530528],[https://chaindesk.cn/witbook/9/73]
一、什么是HD錢包:
它是分層確定性(Hierarchical Deterministic)錢包的縮寫 HD Wallets,是目前廣泛使用的虛擬貨幣錢包標(biāo)準(zhǔn)。HD錢包從單個(gè)根種子(root seed)中創(chuàng)建,為128到256位的隨機(jī)數(shù),任何兼容HD錢包的根種子也可重新創(chuàng)造整個(gè)HD錢包,所以擁有HD錢包的根種子就等于擁有了所有密鑰,方便存儲(chǔ)、導(dǎo)入及導(dǎo)出。
二、BIP32/BIP39/BIP44含義:
BIP32:定義 Hierarchical Deterministic wallet (簡(jiǎn)稱 "HD Wallet"),是一個(gè)系統(tǒng)可以從單一個(gè) seed 產(chǎn)生一樹狀結(jié)構(gòu)儲(chǔ)存多組 keypairs(私鑰和公鑰)。好處是可以方便的備份、轉(zhuǎn)移到其他相容裝置(因?yàn)槎贾恍枰?seed),以及分層的權(quán)限控制等
BIP39:將 seed 用方便記憶和書寫的單字表示。一般由 12 個(gè)單字組成,稱為 mnemonic code(phrase),中文稱為助記詞或助記碼
BIP44:基于 BIP32 的系統(tǒng),賦予樹狀結(jié)構(gòu)中的各層特殊的意義。讓同一個(gè) seed 可以支援多幣種、多帳戶等。各層定義如下:
m / purpose' / coin_type' / account' / change / address_index
其中的 purporse' 固定是 44',代表使用 BIP44。而 coin_type' 用來(lái)表示不同幣種,
例如 BTC :‘0',BTC測(cè)試網(wǎng):‘1’,ETH 是 60' ETC 是 61
change:0表示外部鏈,接收幣;1表示內(nèi)部鏈,找零。
三、多鏈錢包的助記詞、私鑰、地址生成。
安裝 bip39:https://www.npmjs.com/package/bip39
npm install bip39 --save
安裝 ethers.js: https://docs.ethers.io/ethers.js/html/index.html
npm install ethers --save
安裝 bitcoinjs-lib:https://www.npmjs.com/package/bitcoinjs-lib
npm install bitcoinjs-lib --save
安裝 eosjs-ecc:https://github.com/EOSIO/eosjs-ecc#randomkey
npm install eosjs-ecc --save
bip32,ethereumjs-wallet,ethereumjs-util
1、HD錢包助記詞生成:
ethers.js生成助記詞:
let mnemonic = ethers.Wallet.createRandom().mnemonic
bip39生成助記詞:
let mnemonic = bip39.generateMnemonic()
2、BTC錢包通過(guò)助記詞生成私鑰、公鑰、地址:
//設(shè)置生成測(cè)試or正式環(huán)境的錢包
const network = bitcoin.networks.bitcoin
// 計(jì)算seed:
const seed = bip39.mnemonicToSeed(mnemonic,'')
console.log('seed:' + util.bufferToHex(seed), "\n");
const root = bip32.fromSeed(seed,network)
const path = "m/44'/0'/0'/0/0";
const keyPair = root.derivePath(path)
const privateKey = keyPair.toWIF()
console.log("BTC私鑰:", privateKey)
const publicKey = keyPair.publicKey.toString("hex")
console.log("BTC公鑰:", publicKey)
let address = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey , network:network})
console.log("BTC普通地址:", address.address, "\n")
let segwitAddress = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({pubkey: keypair.publicKey, net: net}),
net: net
})
console.log('隔離見(jiàn)證地址:', segwitAddress.address);
使用函數(shù)實(shí)現(xiàn)地址
···
let address = getAddress(keypair, net);
console.log('普通地址:', address);
function getAddress(keypair, net) {
let {address} = bitcoin.payments.p2pkh({pubkey: keypair.publicKey, net: net});
return address;
}
let segwitAddress = getSegwitAddress(keypair, net);
console.log('隔離見(jiàn)證地址:', segwitAddress);
function getSegwitAddress(keypair, net) {
let {address} = bitcoin.payments.p2sh({
redeem: bitcoin.payments.p2wpkh({pubkey: keypair.publicKey, net: net}),
net: net
})
return address;
}
···
3、ETH錢包通過(guò)助記詞生成私鑰、公鑰、地址:
3.1 使用ethers.js
//ethers.js 暫時(shí)不支持通過(guò)添加密碼作為Salt來(lái)保護(hù)種子
let Wallet = ethers.Wallet.fromMnemonic(mnemonic);
let privateKey = Wallet.privateKey;
console.log('ETH私鑰:',privateKey)
let address = Wallet.address;
console.log('ETH地址:',address);
let compressedPublicKey = Wallet.signingKey.keyPair.compressedPublicKey;
console.log('ETH公鑰:',compressedPublicKey)
let newWallet = ethers.Wallet.createRandom();
let mnemonic1 = newWallet.mnemonic;
console.log('mnemonic1:',mnemonic1)
let address1 = newWallet.address;
console.log('address1:',address1);
let privateKey1 = newWallet.privateKey;
console.log('privateKey1:',privateKey);
let compressedPublicKey1 = newWallet.signingKey.keyPair.compressedPublicKey;
console.log('publicKey:',compressedPublicKey1)
3.2 使用ethereumjs-wallet
導(dǎo)入依賴
let hdkey = require('ethereumjs-wallet/hdkey');
let util = require('ethereumjs-util');
let hdwallet = hdkey.fromMasterSeed(seed);
for (let i = 0; i < 3; i++) {
let path = "m/44'/60'/0'/0/" + i;
console.log(path);
let keypair = hdwallet.derivePath(path);
let privateKey = util.bufferToHex(keypair._hdkey._privateKey);
console.log('私鑰:', privateKey);
let publicKey = util.bufferToHex(keypair._hdkey._publicKey);
console.log('公鑰:', publicKey);
let address = util.pubToAddress(keypair._hdkey._publicKey, true);
console.log('地址:', address.toString('hex'))
}