I am implementing bip32 for my wallet as a project to learn Bitcoin.

I am following this documentation: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki

Since I am not implementing bip39 yet, I am getting the master private key and code chain from the BIP39 Root Key from this web: https://iancoleman.io/bip39/#english

using a random set of words which are:

praise vague cruise stem test gesture twin long donate violin special hamster horror rough loan

which throws:


Comparing this output with another web implementation here: https://iancoleman.io/bip39/

These two outputs match. However, after this point they don't. And my implementation doesn't match with any of those implementations!

Here is my python code where I deserialize the BIP32 extended key. This matches perfectly with the master private key and chain code from the second web app:

def deserialize_xprvk(s):
    version = s.read(4)
    depth = s.read(1)
    fingerprint = s.read(4)
    index= s.read(4)
    chain_code = s.read(32)
    privkey = s.read(32)
    return [version,depth, fingerprint,index,chain_code,privkey]

decoded =deserialize_xprvk( BytesIO(decode_base58_extended(xtprvk)))

printing "decoded" I get:


which matches perfectly with the 2nd implementation (the firs one doesn't show the master private key or chain code).

Then I try to follow the instructions from here: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki to derivate the child PRIVATE KEY with index 0 for this master key and chain code like this:

#The order of the ciclic group in the finite field of the ecliptic curve
N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141

#creates a string to emulate the index in a 4-byte hex format.
def str_i(i):
    i_str = hex(i)[2:]
    while len(i_str)<8:
    return i_str

pub_key = PrivateKey(int.from_bytes(master_priv_key,"big")).point.sec()

#I put an extra "0" because every public key begins with a "02" or "03" but
#the hex() function commits this character.
#The str_i(0) means I am trying to get the index 0.
msg=("0" + hex(int.from_bytes(pub_key,"big"))[2:] + str_i(0)).encode() 

I= hmac.new(
            key = hex(int.from_bytes(chain_code,"big"))[2:].encode() ,
            msg=msg ,

I_L, I_R = I[:32], I[32:]

child_privkey_int = (int.from_bytes(I_L,"big") + int.from_bytes(master_priv_key,"big"))%N

child_privkey = PrivateKey(child_privkey_int).wif(compressed= True)

child_chain_code = I_R

If I run this code and try to get the child private key for path m\0\0\ I get:


But in the first web app they get: "KwuPS3DGMnCc3jMJWtqVVzkCoMyhybxGZrf68fPBEBtFfujBdPGs"

And in the second one they get: "L1TcvgkPZFa6DyXhv9vYWceTXZhoAR7ZQMdt5rqV6LW3Zutpsqr8"

Is it ok to disagree on different implementations?? or am I doing something really wrong? I am starting to pull off my hair trying to find out where I am messing up.


  • 1
    Have you tried implementing the BIP32 test vectors? – Pieter Wuille Mar 26 '20 at 1:03
  • never heard of it. – Oscar Serna Mar 26 '20 at 1:06
  • I'll try that. Thanks a lot. – Oscar Serna Mar 26 '20 at 1:09

This line:

msg=("0" + hex(int.from_bytes(pub_key,"big"))[2:] + str_i(0)).encode() 

is incorrect. You are converting the bytes of the pubkey and index into a hex string which you are then hashing. That is not correct. You are supposed to hash the bytes directly, not the hex string.

  • Thanks for your answer. I changed the code, and actually I was doing an unnecessary extra step. However, the outcome is the same. I have looked to other implementations and they look just like mine, but I get a different result. – Oscar Serna Mar 26 '20 at 16:19
  • My line of code now: msg=pub_key + i.to_bytes(4,"big") – Oscar Serna Mar 26 '20 at 16:20
  • Ok. I got it! In my desperation, I had also converted to int the chain code and back to bytes (unnecessary as well) and that was messing up my result. Changing that back along side your suggestion, my results match the vector tests from the Bitcoin Wiki page. Thanks a lot man!! – Oscar Serna Mar 26 '20 at 16:31

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.