I am making an attempt to learn the way HD wallets work internally by writing javascript code that may derive youngster keys from guardian keys. Thus far, the one factor I have been capable of do is convert a BIP39-generated seed to a grasp key and chain code. I can try this efficiently.
Now I want to convert the grasp key to an prolonged key, the lengthy string that begins with xprv
. I would additionally prefer to know methods to derive youngster keys from these, and procure the personal key for signing with any of the accounts.
I have been utilizing this complicated BIP32 doc as a information thus far, however I am getting nowhere with it. So far as I can inform, earlier than you derive any keys, it’s a must to serialize those you have already got.
The serialization course of is described like this:
Prolonged private and non-private keys are serialized as follows:
- 4 byte: model bytes (mainnet: 0x0488B21E public, 0x0488ADE4 personal;
testnet: 0x043587CF public, 0x04358394 personal)- 1 byte: depth: 0x00 for grasp nodes, 0x01 for level-1 derived keys, ….
- 4 bytes: the fingerprint of the guardian’s key (0x00000000 if grasp key)
- 4 bytes: youngster quantity. That is ser32(i) for i in xi = xpar/i, with xi the important thing
being serialized. (0x00000000 if grasp key)- 32 bytes: the chain code
- 33 bytes: the general public key or personal key knowledge (serP(Ok) for public keys,
0x00 || ser256(okay) for personal keys)This 78 byte construction may be
encoded like different Bitcoin knowledge in Base58, by first including 32 checksum
bits (derived from the double SHA-256 checksum), after which changing
to the Base58 illustration. This ends in a Base58-encoded string
of as much as 112 characters. Due to the selection of the model bytes,
the Base58 illustration will begin with “xprv” or “xpub” on mainnet,
“tprv” or “tpub” on testnet.
Right here is the javascript code I wrote in making an attempt to observe these directions.
const crypto = require ('crypto');
const base58 = require ('base58');
const master_key_hex = '5a02ee5cb622f15a4e7ab3dfe7faa9861738da2ae7bb936c685af4dd7b1fbdee';
const chain_code_hex = 'abfbc73691eaad7ca4eb5e25bc51c5804af221cc27a23460634498497f92c92c';
// the 78 bytes of information
var knowledge="0488ade4";
knowledge += '00';
knowledge += '00000000';
knowledge += '00000000';
knowledge += chain_code_hex;
knowledge += '00' + master_key_hex;
// add the checksum
const hash_1 = crypto.createHash ('sha256');
var sha_256_1 = hash_1.replace (knowledge, 'hex').digest ('hex');
const hash_2 = crypto.createHash ('sha256');
var sha_256_2 = hash_2.replace (sha_256_1, 'hex').digest ('hex');
var data_with_checksum = knowledge + sha_256_2;
//knowledge = Buffer.from (data_with_checksum, 'hex');
var consequence = base58.encode (data_with_checksum);
console.log (consequence);
I attempted it with a string and with a Buffer and it gave me the identical error message each instances. The error message is:
Error: Worth handed shouldn't be a non-negative protected integer.
I’ve a sense I’m not even near doing this proper. Does anybody know the way it ought to be coded to derive youngster keys from a grasp key?