]> git.codecow.com Git - libnemo.git/commitdiff
Add support for rederivation when child key is invalid.
authorChris Duncan <chris@codecow.com>
Fri, 15 May 2026 08:17:39 +0000 (01:17 -0700)
committerChris Duncan <chris@codecow.com>
Fri, 15 May 2026 08:17:39 +0000 (01:17 -0700)
src/lib/crypto/bip44.ts

index bdb7fb72278704e29516d599b3c7f100f1c504a4..9ad69e29e32b5647855a5750f26667a7663d484c 100644 (file)
@@ -103,25 +103,31 @@ function CKDpriv (curve: Curve, { privateKey, chainCode }: ExtendedKey, index?:
        const key = chainCode
        const data = t.buffer
        return hmac(key, data)
-               .then(I => childKey(curve, pk, I))
+               .then(I => childKey(curve, pk, chainCode, index, I))
 }
 
-function childKey (curve: Curve, pk: Bytes, I: ArrayBuffer): Promise<ExtendedKey> {
+function childKey (curve: Curve, pk: Bytes, chainCode: ArrayBuffer, index: number, I: ArrayBuffer): Promise<ExtendedKey> {
        const IL = I.slice(0, I.byteLength / 2)
        const IR = I.slice(I.byteLength / 2)
        if (curve === 'ed25519 seed') {
                return Promise.resolve({ privateKey: IL, chainCode: IR })
        }
        const ILparsed = parse256(new Uint8Array(IL))
-       if (ILparsed >= Point.CURVE().n) {
-               throw new Error('Invalid child key is greater than the order of the curve')
+       if (ILparsed < Point.CURVE().n) {
+               const pkParsed = parse256(pk)
+               const ck = (ILparsed + pkParsed) % Point.CURVE().n
+               if (ck !== 0n) {
+                       return Promise.resolve({ privateKey: ser256(ck).buffer, chainCode: IR })
+               }
        }
-       const pkParsed = parse256(pk)
-       const ck = (ILparsed + pkParsed) % Point.CURVE().n
-       if (ck === 0n) {
-               throw new Error('Invalid child key is zero')
-       }
-       return Promise.resolve({ privateKey: ser256(ck).buffer, chainCode: IR })
+       const t = new Uint8Array(37)
+       t.set([1])
+       t.set(new Uint8Array(IR), 1)
+       t.set(ser32(index), 33)
+       const key = chainCode
+       const data = t.buffer
+       return hmac(key, data)
+               .then(I => childKey(curve, pk, chainCode, index, I))
 }
 
 function ser32 (integer: number): Bytes {