Wallet

BIP 32 CKDpriv 在我的 python 實現中不起作用

  • January 31, 2022

我一直致力於在 Python 中實現 BIP 32。這是我作為 HD_Key 類的一部分派生正常(未強化)子密鑰的程式碼:

def CKDpriv(self, index):
   key = bytes.fromhex(self.c) #key for hmac
   K = self.point.sec(compressed=True)
   data = K + index.to_bytes(4, 'big')
   I = hmac.new(key, data, hashlib.sha512).digest()
   L = I[:32]
   R = I[32:]
   ck = S256Field(int.from_bytes(L, 'big')) + S256Field(int(self.k, 16)) #adding two field elements with secp256k1 parameters
   ck = ck.num
   cc = R 
   level = int(self.level) + 1 
   fingerprint = self.get_fingerprint()
   return HD_Key(str(level).zfill(2), fingerprint, hex(index)[2:].zfill(8), hex(ck)[2:], cc.hex())

給定主密鑰:

level: 00, fingerprint: 00000000, index: 00000000, k: 4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e, c: 60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689, testnet: False

當我嘗試使用此程式碼在索引 2 處派生子鍵時,應該是 this: 的 xprvxprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497UHmPB462kDjovoB7YoYXYKYphJVv 實際上是 this: xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497Pku2GX4mxm2YwYKQEr52Q25Z4pip

當我列印出正確擴展私鑰的資訊時,我得到以下資訊:

level: 01, fingerprint: bd16bee5, index: 00000002, key: 32b6b93726e1121f2553bb18ff5b9f263067afe01019538fe34db8761cb94ad0, chain: 4a92983ca7cede2311c61bf911c76d662b0257404659872c792448c09453deba, testnet: False

對於我的程式碼生成的錯誤,我得到了這個:

level: 01, fingerprint: bd16bee5, index: 00000002, key: 32b6b93726e1121f2553bb18ff5b9f24eb168cc6bf61f3cba3201703ecef8fe2, chain: 4a92983ca7cede2311c61bf911c76d662b0257404659872c792448c09453deba, testnet: False

這表明派生的密鑰存在問題。我已經測試了我的擴展密鑰序列化和解析方法,所以我認為問題不包含在這些方法中。什麼可能導致此問題?

它似乎S256Field使用了不正確的模數。您得到了正確的鏈碼,並且密鑰的前半部分是正確的。所以問題是當你做這一步時parse_256(I_L) + k_par (mod n),你n的不正確。

我們可以n通過找出預期鍵和計算鍵之間的差異,並將其添加到n.

0x32b6b93726e1121f2553bb18ff5b9f263067afe01019538fe34db8761cb94ad0 - 0x32b6b93726e1121f2553bb18ff5b9f24eb168cc6bf61f3cba3201703ecef8fe2 = 0x14551231950b75fc4402da1722fc9baee
0x14551231950b75fc4402da1722fc9baee + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f

你的n模是用 is 計算的0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f,這實際上是曲線參數p。但是,您的模需要計算的值是n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141

p是曲線的有限域。它定義了曲線點座標的最大值。你mod p在用曲線點做算術時會這樣做。

n是生成點 G 的階數。它是曲線的離散對數數(私鑰數)。您mod n在使用標量(私鑰)進行算術運算時會這樣做。

由於在此步驟中您要添加兩個標量,因此您需要這樣做mod n而不是mod p.

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