From de56135e1b4337e60f4a5350382e06f15b44ccd7 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Fri, 15 May 2026 01:17:39 -0700 Subject: [PATCH] Add support for rederivation when child key is invalid. --- src/lib/crypto/bip44.ts | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/lib/crypto/bip44.ts b/src/lib/crypto/bip44.ts index bdb7fb7..9ad69e2 100644 --- a/src/lib/crypto/bip44.ts +++ b/src/lib/crypto/bip44.ts @@ -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 { +function childKey (curve: Curve, pk: Bytes, chainCode: ArrayBuffer, index: number, I: ArrayBuffer): Promise { 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 { -- 2.47.3