Bip32-Hd-Wallets

為什麼我的 BIP32 實現與其他 Web 實現會產生不同的結果?他們也彼此不同意

  • March 26, 2020

我正在為我的錢包實施 bip32 作為學習比特幣的項目。

我正在關注此文件: https ://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki

由於我還沒有實現 bip39,我從這個網站的 BIP39 根密鑰獲取主私鑰和程式碼鏈: https ://iancoleman.io/bip39/#english

使用一組隨機的單詞,它們是:

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

拋出:

xprv9s21ZrQH143K2E7weJFDreP9A8dFkx18swFoAJ6DBdsVuSPoFBLzekLca8vEG1i6ikCcvzZb79joaEZAjeM8Nz1DZ549aCnv3YFXy33mLoW

將此輸出與此處的另一個 Web 實現進行比較:https ://iancoleman.io/bip39/

這兩個輸出匹配。然而,在這一點之後,他們沒有。而且我的實現與任何這些實現都不匹配!

這是我的 python 程式碼,我在其中反序列化 BIP32 擴展密鑰。這與第二個 Web 應用程序的主私鑰和鏈碼完美匹配:

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)
   s.read(1)
   privkey = s.read(32)
   return [version,depth, fingerprint,index,chain_code,privkey]

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

列印“解碼”我得到:

0x488ade4
0x0
0x0
0x0
0x10e85c06826fdcd006c244ff6c44200044c1418bdd82cc088c33e48ae7b4c2ca
0xf214c0afd9b311544fdb686cae5100f1ac0ac8aba2b6c55719ba41ac2d4f2d12

這與第二個實現完美匹配(第一個不顯示主私鑰或鏈碼)。

然後我嘗試按照這裡的說明操作: https ://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki 為這個主密鑰和鏈碼派生索引為 0 的子 PRIVATE KEY,如下所示:

#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:
       i_str="0"+i_str
   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 ,
           digestmod=sha512).digest()

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

如果我執行此程式碼並嘗試獲取路徑 m\0\0\ 的子私鑰,我會得到:

“L29Rc5PyDkbUr2z1VcL2DuAhTQkNo3qwF7ENgRotS86ADUkiXPJF”

但在第一個網路應用程序中,他們得到:“KwuPS3DGMnCc3jMJWtqVVzkCoMyhybxGZrf68fPBEBtFfujBdPGs”

在第二個中,他們得到:“L1TcvgkPZFa6DyXhv9vYWceTXZhoAR7ZQMdt5rqV6LW3Zutpsqr8”

可以不同意不同的實現嗎?還是我做錯了什麼?我開始扯掉我的頭髮,試圖找出我在哪裡搞砸了。

謝謝。

這一行:

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

是不正確的。您正在將 pubkey 和索引的字節轉換為一個十六進製字元串,然後您將對其進行散列。這是不正確的。您應該直接散列字節,而不是十六進製字元串。

引用自:https://bitcoin.stackexchange.com/questions/93944