<p>I'm a trying to understand the different encoding on the private keys. What format is used by the <a href="https://iancoleman.io/bip39/" rel="nofollow noreferrer">iancoleman</a> validator and why? How can I reproduce it?
All my Data is valid.</p>
<p>According to the <a href="https://en.bitcoinwiki.org/wiki/Bitcoin_address#How_to_create_Bitcoin_address.3F" rel="nofollow noreferrer">bitcoin wiki</a> The procedure to create a bitcoin address is as follow</p>
<p><a href="https://i.sstatic.net/yRCf4.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/yRCf4.png" alt="Bitcoin address creation" /></a></p>
<p>It seams to me that I have achieve all that with the following code;</p>
<p>First I generate a mnemonic and seed with <a href="https://www.npmjs.com/package/bip39" rel="nofollow noreferrer">BIP39</a>.</p>
<pre><code>    exports.seed = async () =&gt; {
      return new Promise(resolve =&gt; {
        const mnemonic =  bip39.generateMnemonic(); 
        const seed =  bip39.mnemonicToSeed(mnemonic); 
       resolve(seed)
      });
    }
</code></pre>
<p>The mnemonic produced</p>
<blockquote>
<p>drive captain sustain winner neutral anchor congress skirt buzz usage
orient wood</p>
</blockquote>
<p>The seed</p>
<blockquote>
<p>c981bc6db5b0680aa96140f2c9f5f0b910ff69157b01b4de24f9e7590950f44c300386362a0e4ecf109b4c770e74efe81c0b1f673e3de8d1d82a687b1c0d206d</p>
</blockquote>
<p>Now I use that seed to generate a key pair with <a href="https://www.npmjs.com/package/hdkey" rel="nofollow noreferrer">hdkey</a></p>
<pre><code>exports.key = async (seed) =&gt;{
  return new Promise(resolve =&gt; {
  
    const hdkey = HDkey.fromMasterSeed(Buffer.from(seed))
    const masterPrivateKey = hdkey.privateExtendedKey
    const addrnode = hdkey.derive(&quot;m/32'/0'/0'/0&quot;)                    // 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)
  })
}
</code></pre>
<p>So what I can validate so far is that according to this <a href="https://iancoleman.io/bip39/" rel="nofollow noreferrer">BIP39 validator</a></p>
<ul>
<li>The seed generated by the mnemonic is good</li>
<li>The <code>masterPrivatekey</code> is the BIP 32 root key (as per validator)</li>
<li>Both xpub and xprv key are valid with this derivedpath <code>&quot;m/32'/0'/0'/0&quot;</code></li>
</ul>
<p>The address resolve in</p>
<p><strong>1XNR1ABuzSKp4tb3WpF9Yrj88ZBSxMYQ3BnHjtn</strong></p>
<p>This is not a valid address it has 39 characters. The validator, Under the BIP32 tab returns</p>
<p><strong>1B4CKfR96isLCXET5D8jykA2Yz3DBhxAZX</strong></p>
<p>I'm not sure how this address is generated. I think i might be missing a layer in the keys?</p>
<p>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  <code>m/32'/0'/0'/0</code></p>
<p>The validator return a different address with this path <code>m/32'/0'/0'/0/0</code></p>
<p>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.</p>
<p>This are the 2 other modules I use;</p>
<p><a href="https://www.npmjs.com/package/bs58check" rel="nofollow noreferrer">bs58check</a>
<a href="https://www.npmjs.com/package/create-hash" rel="nofollow noreferrer">create-hash</a></p>
<p><strong>UPDATE</strong></p>
<p>Changed the bs58check for <a href="https://www.npmjs.com/package/base58-encode" rel="nofollow noreferrer">base58-encode</a>
I am getting the right address length
By pointing that first address to <code>m/44'/0'/0'/0/0</code>  i have finally obtained
A valid address and a public key</p>
<blockquote>
<p>Address 1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj</p>
</blockquote>
<blockquote>
<p>Public Key 02a84461e76ba44d674d5915b9b48b1bbc0b9b09ccd8e83a43f6d2a42cae78e806</p>
</blockquote>
<p>But the private key is wrong, if I read this account private key like this</p>
<pre><code>const nodeAcc = hdkey.derive(&quot;m/44'/0'/0'/0/0&quot;)
const nodeAccPubKey = nodeAcc._publicKey.toString('hex'))
const nodeAccPrvKey = nodeAcc._privateKey.toString('hex'))
</code></pre>
<p><strong>The private key I get from my code</strong></p>
<blockquote>
<p>6301454cea9ddf9318e7ac82fdfb6edefbf2984384a05c37bdf79258d2331464</p>
</blockquote>
<p>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</p>
<blockquote>
<p>KzYASafouu8yEFUByEt3g9XMAGtbAfqQqgmQxDct4h4kgQzKiXDY</p>
</blockquote>
<p>If I encode that private key in the base58 format I get</p>
<blockquote>
<p>7fUVBZBe47GfV2oMe9RWWaQvBpfh3r2EQuSnv1vCyuqd</p>
</blockquote>
<p>I also found this article that uses <a href="https://en.bitcoin.it/wiki/Wallet_import_format" rel="nofollow noreferrer">WIF format</a></p>
<p>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 <code>0x00</code> and for the WIF Private key we use <code>0x80</code> Both are for main network?</p>
<p>I could validate my WIF with this <a href="https://gobittest.appspot.com/PrivateKey" rel="nofollow noreferrer">tool</a>
My private key WIF</p>
<blockquote>
<p>5JZtXicXZq4crDo32sGeJw3LyUchpWBy9mMV5op6gMQWP636o2m</p>
</blockquote>
<p>So I am wondering which encoding is use by iancoleman's app</p>
<p>I validate my private Key in the Hex format
I Validated my WIF
I have Validate the import process from another wallet (Electrum)</p>
<p>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</p>

CC BY-SA 4.0
2020-12-06T09:06:13.567Z
I don't see why you think the private key is "wrong", it is actually the key for `1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj`.
Claris
CC BY-SA 4.0
2020-12-06T16:21:46.420Z
Which one is good? The last one is from the validator an KzYA.....
The one I get is 63014...
MadeInDreams
CC BY-SA 4.0
2020-12-06T16:23:09.013Z
That’s the private key in hex format.
Claris
CC BY-SA 4.0
2020-12-06T16:23:55.433Z
ok So what format is the KzY one so I can reproduce it.
MadeInDreams
CC BY-SA 4.0
2020-12-06T16:24:37.253Z
that’s just base58.
Claris
CC BY-SA 4.0
2020-12-06T16:28:48.750Z
If I encode it to base 58 i still get a different value
7fUVBZBe47GfV2oMe9RWWaQvBpfh3r2EQuSnv1vCyuqd

How could you tell that this key was good?
MadeInDreams
CC BY-SA 4.0
2020-12-06T16:41:13.587Z
Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/116999/discussion-between-madeindreams-and-anonymous).
MadeInDreams
CC BY-SA 4.0
2020-12-06T22:15:34.883Z
So if it's just base58 why cant'i reproduce it by encoding my key to base58 instead of Hex ?? My WIF is valid and it is not that.
MadeInDreams
CC BY-SA 4.0
2020-12-07T04:15:22.517Z
I think you should start with understanding addresses and WIFs before trying to roll your own from an xpub or xprv.  Your hex private key 6301454cea9ddf9318e7ac82fdfb6edefbf2984384a05c37bdf79258d2331464 has a compressed WIF: KzYASafouu8yEFUByEt3g9XMAGtbAfqQqgmQxDct4h4kgQzKiXDY, Addr: 1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj , and the uncompressed WIF: 5JZtXicXZq4crDo32sGeJw3LyUchpWBy9mMV5op6gMQWP636o2m, Addr: 16HUmgrkTeMCK4aaCrmjracBhw2MVWm2Z9
m1xolyd1an
CC BY-SA 4.0
2020-12-07T04:28:04.387Z
So how do I generate the compressed version of it? And what is it used for. It doesn't look any smaller than the uncompressed version. I am further in the code now and I validated my wallets against Electreum and Metamask. I could import both and got all the right adresses along so my understanding is a bit further now. This is also what I'm asking. How to get the compressed version.
MadeInDreams
<bip32-hd-wallets><base58check>
How to get the compressed WIF of my key?
MadeInDreams
# How to get the compressed WIF of my key?

(Asked by: username_0 on 2020-12-06)

I'm a trying to understand the different encoding on the private keys. What format is used by the [iancoleman](https://iancoleman.io/bip39/) validator and why? How can I reproduce it?
All my Data is valid.

According to the [bitcoin wiki](https://en.bitcoinwiki.org/wiki/Bitcoin_address#How_to_create_Bitcoin_address.3F) The procedure to create a bitcoin address is as follow

[![Bitcoin address creation](https://i.sstatic.net/yRCf4.png)](https://i.sstatic.net/yRCf4.png)

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

First I generate a mnemonic and seed with [BIP39](https://www.npmjs.com/package/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](https://www.npmjs.com/package/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](https://iancoleman.io/bip39/)

* 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](https://www.npmjs.com/package/bs58check)
[create-hash](https://www.npmjs.com/package/create-hash)

**UPDATE**

Changed the bs58check for [base58-encode](https://www.npmjs.com/package/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](https://en.bitcoin.it/wiki/Wallet_import_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](https://gobittest.appspot.com/PrivateKey)
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

**Tags:** bip32-hd-wallets, base58check

> **Comments:**
> **username_1**: I don't see why you think the private key is "wrong", it is actually the key for `1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj`.  
> **username_0**: Which one is good? The last one is from the validator an KzYA..... The one I get is 63014...  
> **username_1**: That’s the private key in hex format.  
> **username_0**: ok So what format is the KzY one so I can reproduce it.  
> **username_1**: that’s just base58.  
> **username_0**: If I encode it to base 58 i still get a different value 7fUVBZBe47GfV2oMe9RWWaQvBpfh3r2EQuSnv1vCyuqd  How could you tell that this key was good?  
> **username_0**: Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/116999/discussion-between-username_0-and-anonymous).  
> **username_0**: So if it's just base58 why cant'i reproduce it by encoding my key to base58 instead of Hex ?? My WIF is valid and it is not that.  
> **username_2**: I think you should start with understanding addresses and WIFs before trying to roll your own from an xpub or xprv.  Your hex private key 6301454cea9ddf9318e7ac82fdfb6edefbf2984384a05c37bdf79258d2331464 has a compressed WIF: KzYASafouu8yEFUByEt3g9XMAGtbAfqQqgmQxDct4h4kgQzKiXDY, Addr: 1HaGGkWmUDTKExFxyXaiGHHPxYNaCefQrj , and the uncompressed WIF: 5JZtXicXZq4crDo32sGeJw3LyUchpWBy9mMV5op6gMQWP636o2m, Addr: 16HUmgrkTeMCK4aaCrmjracBhw2MVWm2Z9  
> **username_0**: So how do I generate the compressed version of it? And what is it used for. It doesn't look any smaller than the uncompressed version. I am further in the code now and I validated my wallets against Electreum and Metamask. I could import both and got all the right adresses along so my understanding is a bit further now. This is also what I'm asking. How to get the compressed version.  

---

## 0 answers

