1

i tried to replicate code in this git https://github.com/tongokongo/bitcoin-basics/blob/master/HD_wallet/bip32.py .

I'm not familiar with python but the xpub is correct (this is the Test Vector 1 from BIP32) while the xpriv is:

b'Har3K3MhV5fiuEp6ztqjoMJejPsfnrLHAzSWDpkzLGomKaoUPLkSrwPxsdKMbzgsi6eegKG5BMwPyk8RMbDEe6zpHSUnRZMNJkX2HEhDzo41ds7qJVyRkhb3jsGezXb8XB4hW12QKUuxc3pDstNHMuYwEyV'

b'xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8'

what's the mistake?

Below the code:

import binascii
import hmac
import hashlib
import struct
import ecdsa
import base58
from ecdsa.curves import SECP256k1
from ecdsa.ecdsa import int_to_string, string_to_int


#chain m
seed = binascii.unhexlify("000102030405060708090a0b0c0d0e0f") #generiamo il seed, importiamo la stringa del test vector
#calcolaiamo ora I come HMAC-SHA512 (seed key="Bitcoin seed" Data = seed) - occorre importare hmac e hashlib
I = hmac.new(b"Bitcoin seed", seed, hashlib.sha512).digest()
#il risultato ottenuto va diviso in 2 stringhe da 32bytes (Il & Ir)
Il, Ir= I[:32], I[32:]

#il risultato va serializzato come descritto dal BIP32
#priv=xpriv+depth(1byte)+fingerprint(4bytes)+chaincode(32bytes)+chiave(33bytes)
#pub=xpub+depth(1byte)+fingerprint(4bytes)+chaincode(32bytes)+chiave(33bytes)

secret = Il #parte sinistra ottenuta dal HMAC
chain = Ir #parte destra
xprv = binascii.unhexlify("0488ade4") #è la version di default per la mainnet di Bicoin
xpub = binascii.unhexlify("0488b21e") #è la version di default per la mainnet di Bicoin
depth = b"\x00" #come da guida a livello della master  "0x00 for master nodes"
fingerp= b"\0\0\0\0" #come da guida a livello dalla master "(0x00000000 if master key)"
index = 0 #index del child al livello della master
child = struct.pack('>L', index) # L = big endian, the way of storing values starting from most significant value in sequence

#importare ECDSA dopo averlo installato. Occorreranno inoltre le librerie:
#from ecdsa.curves import SECP256k1
#from ecdsa.ecdsa import int_to_string, string_to_int
k_priv = ecdsa.SigningKey.from_string(secret, curve=SECP256k1)
k_priv = k_priv.get_verifying_key()


#bisogna ora serializzare la chiave privata come 32bytes con 00 davanti
data_priv = b'\x00' + (k_priv.to_string())

# serialization the coordinate pair P = (x,y) as a byte sequence using SEC1's compressed form
if k_priv.pubkey.point.y() & 1:
    data_pub = b'\3' + int_to_string(k_priv.pubkey.point.x())
else:
    data_pub = b'\2' + int_to_string(k_priv.pubkey.point.x())

raw_priv = xprv + depth + fingerp + child + chain + data_priv
raw_pub = xpub + depth + fingerp + child + chain + data_pub
#print(raw_priv)
#print(raw_pub)
#a questo punto abbiamo ottenuto due strutture da 78 byte che possono essere Codificate base58. Occore però prima trovare e concatenare
#il cheksum da 32 bits (4 bytes). Il Checksum si ottiene con un doppio SHA256

hashed_xprv = hashlib.sha256(raw_priv).digest()
hashed_xprv = hashlib.sha256(hashed_xprv).digest()
hashed_xpub = hashlib.sha256(raw_pub).digest()
hashed_xpub = hashlib.sha256(hashed_xpub).digest()


#vogliamo aggiungere a raw_priv e raw_pub gli ultimi 4 bytes dei digest ottenuti

raw_priv += hashed_xprv[:4]
raw_pub += hashed_xpub[:4]

#codifichiamo ora base58 - importare prima il pacchetto
print(base58.b58encode(raw_priv))
print(base58.b58encode(raw_pub))
0

It's code from my video. In k_priv = k_priv.get_verifying_key() it should be capital K, I was trying to be as close to original biputils lib as possible, Then you use it in pubkey related data derivation:

if K_priv.pubkey.point.y() & 1:
    data_pub= b'\3'+int_to_string(K_priv.pubkey.point.x())  
else:
    data_pub = b'\2'+int_to_string(K_priv.pubkey.point.x())

Sorry for making it confusing, I'll try to represent it better next time :)

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.