【原理篇】以太坊钱包区块链中的一些加密算法总结(秘钥推到、HD助记词分层推倒、KeyStore文件推倒)
bip44官方文档:https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
BIP44比特币路径推倒的规则:
m / purpose' / coin_type' / account' / change / address_index
//purporse': 固定值44', 代表是BIP44
//coin_type': 这个代表的是币种, 可以兼容很多种币, 比如BTC是0', ETH是60'
//btc一般是 m/44'/0'/0'/0
//eth一般是 m/44'/60'/0'/0
参考链接:https://www.jianshu.com/p/54a2b14dfdf2
助记词推导账号的底层原理:利用最底层的hash散列算法库来实现!
/**
* 原理篇:利用最底层的hash散列算法库来实现助记词推导账号的原理!
**/
const bip39 = require('bip39');
const hdkey = require('ethereumjs-wallet/hdkey');
const util = require('ethereumjs-util');
// 助记词推导钱包地址的class
class HDWalletMnemonic {
constructor() {
this.hd_wallet = null;
this.address = {};
}
get_hd_wallet(mnemonic=null) {
if (!mnemonic) {
//第一步:如果没提供助记词mnemonic,那就随机生成助记词!
mnemonic = bip39.generateMnemonic();
}
// 第二步:把助记词转换成种子seed_buffer
let seed_buffer = bip39.mnemonicToSeed(mnemonic);
// 第三步:通过种子seed_buffer创建hd钱包
this.hd_wallet = hdkey.fromMasterSeed(seed_buffer);
}
deduce_address(num) {
while (num >= 0) {
// 第四步:从hdwallet的路径推倒规则中获取**对
let keypair1 = this.hd_wallet.derivePath(`m/44'/60'/0'/0/${num}`);
// 第五步:从keypair获得公钥,然后用公钥推倒地址!
this.address[`${num}`] = util.bufferToHex(util.publicToAddress(keypair1._hdkey._publicKey, true))
num--;
}
}
}
let mnemonic = "squeeze bounce always pencil often grain ensure robot clerk purchase frequent toy"
hd = new HDWalletMnemonic();
hd.get_hd_wallet(mnemonic);
hd.deduce_address(10);
console.log("all addres:", hd.address);
秘钥推导账号的原理:利用最底层的hash散列算法库来实现!
/**
* 原理篇:利用最底层的hash散列算法库来实现秘钥推导账号的原理!
**/
const crypto = require("crypto");
const secp256k1 = require("secp256k1");
const createKeccakHash = require("keccak");
function private_key_deduce_address(private_key = null) {
if (!private_key) {
// 如果没有提供私钥就随便创建一个
private_key = crypto.randomBytes(32);
} else {
// 兼容输入0x开头的秘钥
if (private_key.startsWith("0x")) {
private_key = private_key.slice(2);
}
// 私钥必须转换成Buffer
private_key = Buffer.from(private_key, 'hex');
}
// 确保私钥匙有效的
if (!secp256k1.privateKeyVerify(private_key)) {
throw Error(`${private_key}私钥错误!`);
}
// 注:slice(1)就是丢掉第0位(从第一位开始截断)
let public_key = secp256k1.publicKeyCreate(private_key, false).slice(1);
// 注:publicKeyCreate方法第二个属性compressed必须设置为false,否则无法输出正确的结果!
let hash = createKeccakHash('keccak256').update(public_key).digest('hex');
console.log(`hash值为:0x${hash}`);
// 取hash的后40位即为地址!
let address = hash.slice(-40);
console.log(`addres值为:0x${address}`);
}
private_key_deduce_address("0x0c9a5047ec90238e1ba447d4eb45a8e60d8a48b75b655f99fcadad59a86a5c7b");
KeyStore文件推导账号的原理 :