Bip32-Hd-Wallets

從python中的擴展公鑰生成公鑰

  • July 28, 2022

我想從 Python 中的擴展公鑰中獲取普通公鑰。實際上,我想在擴展公鑰子部分中獲得與此處相同的結果。我知道我需要這個結構:

child_public_key = parent_public_key + point(lefthand_hash_output)

我用它來獲取左手雜湊:

        0x00 not sure if I need this                                         Index
        --                                                                  --------             
pub_key="000343b337dec65a47b3362c9620a6e6ff39a1ddfa908abab1666c8a30a3f8a7cccc00000000"
chain_code="1d7d2a4c940be028b945302ad79dd2ce2afe5ed55e1a2937a5af57f8401e73dd"

h = hmac.new( chain_code.encode("utf-8"),pub_key.encode("utf-8"), hashlib.sha512 ).digest()
lefthand_hash_output=slice(0,len(h)//2)

但現在我不知道如何製作這個point(lefthand_hash_output)

我也試過這個,但出錯了

seed=b'...' # replaced with the seed
root_key = bip32utils.BIP32Key.fromEntropy(seed)
root_public_hex = root_key.PublicKey().hex()
key=bip32utils.BIP32Key.CKDpub((root_public_hex) ,0)
print(key)

範例原始碼將非常有幫助。提前致謝!

從擴展公鑰到子公鑰的轉換在BIP32中指定:

函式 CKDpub((K par , c par ), i) → (K i , c i ) 從父擴展公鑰計運算元擴展公鑰。它僅針對非強化子鍵定義。

  • 檢查是否 i ≥ 2 31(孩子是否是硬鍵)。

+ 如果是這樣(硬化的孩子):返回失敗 + 如果不是(正常孩子):讓 I = HMAC-SHA512(Key = c par , Data = ser P (K par ) || ser 32 (i))。

  • 將 I 拆分為兩個 32 字節序列,即 I L和 I R。
  • 返回的子鍵 K i是 point(parse 256 (I L )) + K par。
  • 返回的鏈碼 c i是 I R。
  • 如果解析256 (I L ) ≥ n 或 K i是無窮遠點,則生成的鍵是無效的,應該繼續 i 的下一個值。

其他使用的函式定義如下:

  • point(p):返回 secp256k1 基點與整數 p 的 EC 點乘法(重複應用 EC 組運算)得到的座標對。
  • ser 32 (i):將 32 位無符號整數 i 序列化為 4 字節序列,最高有效字節在前。
  • ser 256 (p):將整數 p 序列化為 32 字節序列,最高有效字節在前。
  • ser P (P):使用SEC1的壓縮形式將座標對P = (x,y)序列化為字節序列:(0x02 or 0x03) || ser 256 (x),其中標頭字節取決於省略的 y 座標的奇偶性。
  • 解析256 (p):將 32 字節序列解釋為 256 位數字,最高有效字節在前。

我在您的程式碼中看到的第一個問題是您的公鑰長度為 34 個字節。根據規範,它應該是 33 字節長,並以 0x02 或 0x03 開頭。

接下來,chain_code.encode("utf-8")不將十六進製字元串轉換為字節。改用類似的東西bytes.fromhex(chain_code)

最後,lefthand_hash_output是創建錯了,應該是h[:32]

對於範例原始碼,您應該查看python-bip32中的實現。它使用coincurve進行 secp256k1 曲線操作。

def _derive_public_child(pubkey, chaincode, index):
   """A.k.a CKDpub, in bip-0032.

   :param pubkey: The parent's (compressed) public key, as bytes
   :param chaincode: The parent's chaincode, as bytes
   :param index: The index of the node to derive, as int

   :return: (child_pubkey, child_chaincode)
   """
   assert isinstance(pubkey, bytes) and isinstance(chaincode, bytes)
   assert not index & HARDENED_INDEX
   # payload is the I from the BIP. Index is 32 bits unsigned int, BE.
   payload = hmac.new(
       chaincode, pubkey + index.to_bytes(4, "big"), hashlib.sha512
   ).digest()
   try:
       tmp_pub = coincurve.PublicKey.from_secret(payload[:32])
   except ValueError:
       raise BIP32DerivationError(
           "Invalid private key at index {}, try the " "next one!".format(index)
       )
   parent_pub = coincurve.PublicKey(pubkey)
   try:
       child_pub = coincurve.PublicKey.combine_keys([tmp_pub, parent_pub])
   except ValueError:
       raise BIP32DerivationError(
           "Invalid public key at index {}, try the " "next one!".format(index)
       )
   return child_pub.format(), payload[32:]

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