Bip32-Hd-Wallets
從python中的擴展公鑰生成公鑰
我想從 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:]