BIP 32 CKDpriv 在我的 python 實現中不起作用
我一直致力於在 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: 的 xprv
xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497UHmPB462kDjovoB7YoYXYKYphJVv
實際上是 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
.