1

I'm a trying to understand the different encoding on the private keys. What format is used by the iancoleman validator and why? How can I reproduce it? All my Data is valid.

According to the bitcoin wiki The procedure to create a bitcoin address is as follow

Bitcoin address creation

It seams to me that I have achieve all that with the following code;

First I generate a mnemonic and seed with BIP39.

    exports.seed = async () => {
      return new Promise(resolve => {
        const mnemonic =  bip39.generateMnemonic(); 
        const seed =  bip39.mnemonicToSeed(mnemonic); 
       resolve(seed)
      });
    }

The mnemonic produced

drive captain sustain winner neutral anchor congress skirt buzz usage orient wood

The seed

c981bc6db5b0680aa96140f2c9f5f0b910ff69157b01b4de24f9e7590950f44c300386362a0e4ecf109b4c770e74efe81c0b1f673e3de8d1d82a687b1c0d206d

Now I use that seed to generate a key pair with hdkey

exports.key = async (seed) =>{
  return new Promise(resolve => {
  
    const hdkey = HDkey.fromMasterSeed(Buffer.from(seed))
    const masterPrivateKey = hdkey.privateExtendedKey
    const addrnode = hdkey.derive("m/32'/0'/0'/0")                    // derived path
    const nodePubKey = addrnode.publicExtendedKey  


    const sha256 = createHash('sha256').update(nodePubKey).digest()
    const pipedMd = createHash('rmd160').update(sha256).digest()      // 20 bytes hash
 
   
    var fingerprint = Buffer.allocUnsafe(21)                          // fingerprint 20+1 bytes

    fingerprint.writeUInt8(0x00, 0)                                   // 0x00 network byte
    pipedMd.copy(fingerprint,1) 


    var sha1 = createHash('sha256').update(fingerprint).digest()
    var sha2 = createHash('sha256').update(sha1).digest()
    var checksum = sha2.slice(0,4)                                  // checksum 4 bytes

    var rawAddr = Buffer.allocUnsafe(25)                            // raw address 25 bytes

    fingerprint.copy(rawAddr,0)                                     // fingerprint 21 bytes + checksum 4
    checksum.copy(rawAddr,21) 

    var address = bs58check.encode(rawAddr)                         // base58 encode the raw address

    resolve(address)
  })
}

So what I can validate so far is that according to this BIP39 validator

  • The seed generated by the mnemonic is good
  • The masterPrivatekey is the BIP 32 root key (as per validator)
  • Both xpub and xprv key are valid with this derivedpath "m/32'/0'/0'/0"

The address resolve in

1XNR1ABuzSKp4tb3WpF9Yrj88ZBSxMYQ3BnHjtn

This is not a valid address it has 39 characters. The validator, Under the BIP32 tab returns

1B4CKfR96isLCXET5D8jykA2Yz3DBhxAZX

I'm not sure how this address is generated. I think i might be missing a layer in the keys?

Should I use the BIP32 extended xpub key and derive some more keys out of it. My reasoning behind this is that I derived a keys pair from m/32'/0'/0'/0

The validator return a different address with this path m/32'/0'/0'/0/0

So the problem has to be from the concatenation of the networkid + fingerprint + checksum or the base58 encoding. I'm also not sure if the network byte should be added to the fingerprint before the 2 SHA256 hash checksum or after.

This are the 2 other modules I use;

bs58check create-hash

UPDATE

Changed the bs58check for base58-encode I am getting the right address length By pointing that first address to m/44'/0'/0'/0/0 i have finally obtained A valid address and a public key

Address 1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj

Public Key 02a84461e76ba44d674d5915b9b48b1bbc0b9b09ccd8e83a43f6d2a42cae78e806

But the private key is wrong, if I read this account private key like this

const nodeAcc = hdkey.derive("m/44'/0'/0'/0/0")
const nodeAccPubKey = nodeAcc._publicKey.toString('hex'))
const nodeAccPrvKey = nodeAcc._privateKey.toString('hex'))

The private key I get from my code

6301454cea9ddf9318e7ac82fdfb6edefbf2984384a05c37bdf79258d2331464

IT seams to me I'm not getting the right format. The private key the BIP39 validator is giving me for my address is this

KzYASafouu8yEFUByEt3g9XMAGtbAfqQqgmQxDct4h4kgQzKiXDY

If I encode that private key in the base58 format I get

7fUVBZBe47GfV2oMe9RWWaQvBpfh3r2EQuSnv1vCyuqd

I also found this article that uses WIF format

They basically say that to generate a WIF private key I have to repeat the Network byte and checksum process. I don't understand why in the case of the address generation we use the network byte 0x00 and for the WIF Private key we use 0x80 Both are for main network?

I could validate my WIF with this tool My private key WIF

5JZtXicXZq4crDo32sGeJw3LyUchpWBy9mMV5op6gMQWP636o2m

So I am wondering which encoding is use by iancoleman's app

I validate my private Key in the Hex format I Validated my WIF I have Validate the import process from another wallet (Electrum)

I know that in the end the key will be used in the byte format but I would still like to understand why I'm not able to match it to the validator

10
  • 1
    I don't see why you think the private key is "wrong", it is actually the key for 1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj. – Anonymous Dec 6 '20 at 9:06
  • Which one is good? The last one is from the validator an KzYA..... The one I get is 63014... – MadeInDreams Dec 6 '20 at 16:21
  • 1
    That’s the private key in hex format. – Anonymous Dec 6 '20 at 16:23
  • ok So what format is the KzY one so I can reproduce it. – MadeInDreams Dec 6 '20 at 16:23
  • 1
    that’s just base58. – Anonymous Dec 6 '20 at 16:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.