為什麼我的 BIP32 實現與其他 Web 實現會產生不同的結果?他們也彼此不同意
我正在為我的錢包實施 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 和索引的字節轉換為一個十六進製字元串,然後您將對其進行散列。這是不正確的。您應該直接散列字節,而不是十六進製字元串。