0

I have a small Python program I'm writing to generate BIP32 keys, including child keys. I've gotten to the point where I can correctly generate a master extended key pair, but I'm not able to correctly derive a child private key and chain code. I've copied my code below:

import hmac
import struct
from hashlib import sha512

def CKDprv(chain, data):
  data = data.to_bytes(33, 'big') + struct.pack('>L', 0)
  return hmac.new(chain.to_bytes(32, 'big'), data, sha512).digest()

def split_key(key):
  length = len(key) // 2
  return key[:length], key[length:]

pub = 0x0339a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2
chain = 0x873dff81c02f525623fd1fe5167eac3a55a049de3d314bb42ee227ffed37d508

digest = CKDprv(chain, pub)
new_prv, new_chain = split_key(digest)
print(f'Chain code: {new_chain.hex()}')

I am using some BIP32 test vectors and trying to derive m/0' from m. I am deriving a child key with index 0, so I am hashing the parent compressed public key appended with the index represented in 4 bytes. According to the test vectors, the new chain code I should be deriving is:

47fdacbd0f1097043b78c63c20c34ef4ed9a111d980047ad16282c7ae6236141

but the chain code I receive from my function is:

d323f1be5af39a2d2f08f5e8f664633849653dbe329802e9847cfc85f8d7b52a

I've tried variations such as changing endianness, but nothing seems to get me the correct hash. I know I've probably made a small programming error that is throwing me off completely, and I've been staring at this problem with no progress for a few days now. If anyone can point out the flaw in my algorithm I would be greatly appreciated.

1

Ended up answering my own question! If anyone else runs into a situation like this, the problem is that the code is deriving a non-hardened child key but checking for the hash associated with a hardened child key. According to the BIP32 docs, to derive a child key you hash the private key prepended with a single zeroed out byte and appended with a hardened index (greater than or equal to 2^31). So in this case, I only needed to swap out the public key for the private key, prepend it with a single 0x00 byte, and use the first child hardened integer 0x80000000 instead of 0x00000000.

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.