<p>It appears <code>S256Field</code> uses the incorrect modulo. You arrive at the correct chaincode, and the first half of the key is correct. So the issue is that when you do the step <code>parse_256(I_L) + k_par (mod n)</code>, your <code>n</code> is incorrect.</p>
<p>We can reverse engineer what value you used for <code>n</code> by finding the difference between the expected key and the calculated key, and adding that to the real value of <code>n</code>.</p>
<pre><code>0x32b6b93726e1121f2553bb18ff5b9f263067afe01019538fe34db8761cb94ad0 - 0x32b6b93726e1121f2553bb18ff5b9f24eb168cc6bf61f3cba3201703ecef8fe2 = 0x14551231950b75fc4402da1722fc9baee
0x14551231950b75fc4402da1722fc9baee + 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 = 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f
</code></pre>
<p>The <code>n</code> your modulo is computed with is <code>0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f</code>, which is actually the curve parameter <code>p</code>. However the value your modulo needs to be computed with is <code>n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141</code>.</p>
<p><code>p</code> is the finite field for the curve. It defines that largest value for the coordinates of a curve point. You do <code>mod p</code> when doing arithmetic with curve points.</p>
<p><code>n</code> is the order of the generator point G. It is the number of discrete logarithms (number of private keys) for the curve. You do <code>mod n</code> when doing arithmetic with scalars (private keys).</p>
<p>Since in this step you are adding two scalars, you need to be doing it <code>mod n</code> rather than <code>mod p</code>.</p>

CC BY-SA 4.0
2022-01-31T21:38:42.953Z
Thanks for the clear response, it's working now.
ana408
CC BY-SA 4.0
2022-01-31T16:37:02.010Z
2022-01-31T16:42:23.427Z
2022-01-31T16:42:23.427Z
Ava Chow
<p>I have been working on implementing BIP 32 in Python. This is my code for deriving normal (not hardened) child keys as part of an HD_Key class:</p>
<pre><code>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())
</code></pre>
<p>Given master key:</p>
<pre><code>level: 00, fingerprint: 00000000, index: 00000000, k: 4b03d6fc340455b363f51020ad3ecca4f0850280cf436c70c727923f6db46c3e, c: 60499f801b896d83179a4374aeb7822aaeaceaa0db1f85ee3e904c4defbd9689, testnet: False
</code></pre>
<p>when I try to derive a child key at index 2 using this code, the xprv which is supposed to be this: <code>xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497UHmPB462kDjovoB7YoYXYKYphJVv</code>
is actually this: <code>xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497Pku2GX4mxm2YwYKQEr52Q25Z4pip</code>.</p>
<p>When I print out the information for the correct extended private key I get this:</p>
<pre><code>level: 01, fingerprint: bd16bee5, index: 00000002, key: 32b6b93726e1121f2553bb18ff5b9f263067afe01019538fe34db8761cb94ad0, chain: 4a92983ca7cede2311c61bf911c76d662b0257404659872c792448c09453deba, testnet: False
</code></pre>
<p>And for the incorrect one which my code generated I get this:</p>
<pre><code>level: 01, fingerprint: bd16bee5, index: 00000002, key: 32b6b93726e1121f2553bb18ff5b9f24eb168cc6bf61f3cba3201703ecef8fe2, chain: 4a92983ca7cede2311c61bf911c76d662b0257404659872c792448c09453deba, testnet: False
</code></pre>
<p>This indicates that there is a problem with the key being derived. I've tested my extended key serialization and parsing methods, so I don't think that the issue is contained within those. What could be causing this issue?</p>

<wallet><bip32-hd-wallets><python><cryptography>
BIP 32 CKDpriv not working in my python implementation
ana408
# BIP 32 CKDpriv not working in my python implementation

(Asked by: username_0 on 2022-01-31)

I have been working on implementing BIP 32 in Python. This is my code for deriving normal (not hardened) child keys as part of an HD\_Key class:

```
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())

```

Given master key:

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

```

when I try to derive a child key at index 2 using this code, the xprv which is supposed to be this: `xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497UHmPB462kDjovoB7YoYXYKYphJVv`
is actually this: `xprv9vHkqa6EV4sPcjMMuDToT9SVa6UHCwR4pxvYKZdKTqWpcgQqmPuphAbteLtH9GTXaB87d9zYGuVN497Pku2GX4mxm2YwYKQEr52Q25Z4pip`.

When I print out the information for the correct extended private key I get this:

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

```

And for the incorrect one which my code generated I get this:

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

```

This indicates that there is a problem with the key being derived. I've tested my extended key serialization and parsing methods, so I don't think that the issue is contained within those. What could be causing this issue?

**Tags:** wallet, bip32-hd-wallets, python, cryptography


---

## 1 answers

### Answer by username_1 on 2022-01-31. Score: 2 | Accepted answer

It appears `S256Field` uses the incorrect modulo. You arrive at the correct chaincode, and the first half of the key is correct. So the issue is that when you do the step `parse_256(I_L) + k_par (mod n)`, your `n` is incorrect.

We can reverse engineer what value you used for `n` by finding the difference between the expected key and the calculated key, and adding that to the real value of `n`.

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

```

The `n` your modulo is computed with is `0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f`, which is actually the curve parameter `p`. However the value your modulo needs to be computed with is `n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141`.

`p` is the finite field for the curve. It defines that largest value for the coordinates of a curve point. You do `mod p` when doing arithmetic with curve points.

`n` is the order of the generator point G. It is the number of discrete logarithms (number of private keys) for the curve. You do `mod n` when doing arithmetic with scalars (private keys).

Since in this step you are adding two scalars, you need to be doing it `mod n` rather than `mod p`.

> **Comments:**
> **username_0**: Thanks for the clear response, it's working now.  

---

