From 191f978216dbdcefed23e49832d9b8f4d4bcce38 Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Mon, 16 Dec 2024 11:30:55 -0800 Subject: [PATCH] Convert BIP44 ckd to class and update imports in worker. --- src/lib/workers.ts | 6 ++-- src/lib/workers/bip44-ckd.ts | 59 ++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/src/lib/workers.ts b/src/lib/workers.ts index d6d03a7..61a1b6d 100644 --- a/src/lib/workers.ts +++ b/src/lib/workers.ts @@ -1,4 +1,4 @@ -import { Bip44Ckd, worker as Bip44CkdWorker } from './workers/bip44-ckd.js' +import { Bip44Ckd } from './workers/bip44-ckd.js' import { NanoNaCl, worker as NanoNaClWorker } from './workers/nano-nacl.js' // import './workers/passkey.js' import { Pow } from './workers/pow.js' @@ -81,9 +81,9 @@ const w = () => { } } -const bip44ckd = `const Bip44Ckd = () => {\n${Bip44CkdWorker}\n}\n` +const bip44ckd = `const Bip44Ckd = ${Bip44Ckd}\n` const nanonacl = `const NanoNaCl = () => {\n${NanoNaClWorker}\n}\n` -const pow = `const Pow = ${Pow}` +const pow = `const Pow = ${Pow}\n` const start = w.toString().indexOf('{') + 1 const end = w.toString().lastIndexOf('}') const body = w.toString().substring(start, end) diff --git a/src/lib/workers/bip44-ckd.ts b/src/lib/workers/bip44-ckd.ts index aca7869..300cb8a 100644 --- a/src/lib/workers/bip44-ckd.ts +++ b/src/lib/workers/bip44-ckd.ts @@ -6,20 +6,19 @@ type ExtendedKey = { chainCode: DataView } -const b = () => { +export class Bip44Ckd { - const BIP44_COIN_NANO = 165 - const BIP44_PURPOSE = 44 - const HARDENED_OFFSET = 0x80000000 - const SLIP10_ED25519 = 'ed25519 seed' + static BIP44_COIN_NANO = 165 + static BIP44_PURPOSE = 44 + static HARDENED_OFFSET = 0x80000000 + static SLIP10_ED25519 = 'ed25519 seed' - - async function calculate (data: any[]): Promise { + static async calculate (data: any[]): Promise { for (const d of data) { - if (d.coin != null && d.coin !== BIP44_PURPOSE) { - d.privateKey = await ckd(d.seed, d.coin, d.index) + if (d.coin != null && d.coin !== this.BIP44_PURPOSE) { + d.privateKey = await this.ckd(d.seed, d.coin, d.index) } else { - d.privateKey = await nanoCKD(d.seed, d.index) + d.privateKey = await this.nanoCKD(d.seed, d.index) } } return data @@ -33,11 +32,11 @@ const b = () => { * @param {number} index - Account number between 0 and 2^31-1 * @returns {Promise} Private child key for the account */ - async function nanoCKD (seed: string, index: number): Promise { + static async nanoCKD (seed: string, index: number): Promise { if (!Number.isSafeInteger(index) || index < 0 || index > 0x7fffffff) { throw new RangeError(`Invalid child key index 0x${index.toString(16)}`) } - return await ckd(seed, BIP44_COIN_NANO, index) + return await this.ckd(seed, this.BIP44_COIN_NANO, index) } /** @@ -50,17 +49,17 @@ const b = () => { * @param {number} index - Account number between 0 and 2^31-1 * @returns {Promise} Private child key for the account */ - async function ckd (seed: string, coin: number, index: number): Promise { + static async ckd (seed: string, coin: number, index: number): Promise { if (seed.length < 32 || seed.length > 128) { throw new RangeError(`Invalid seed length`) } if (!Number.isSafeInteger(index) || index < 0 || index > 0x7fffffff) { throw new RangeError(`Invalid child key index 0x${index.toString(16)}`) } - const masterKey = await slip10(SLIP10_ED25519, seed) - const purposeKey = await CKDpriv(masterKey, BIP44_PURPOSE + HARDENED_OFFSET) - const coinKey = await CKDpriv(purposeKey, coin + HARDENED_OFFSET) - const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET) + const masterKey = await this.slip10(this.SLIP10_ED25519, seed) + const purposeKey = await this.CKDpriv(masterKey, this.BIP44_PURPOSE + this.HARDENED_OFFSET) + const coinKey = await this.CKDpriv(purposeKey, coin + this.HARDENED_OFFSET) + const accountKey = await this.CKDpriv(coinKey, index + this.HARDENED_OFFSET) const privateKey = new Uint8Array(accountKey.privateKey.buffer) let hex = '' for (let i = 0; i < privateKey.length; i++) { @@ -69,29 +68,29 @@ const b = () => { return hex } - async function slip10 (curve: string, S: string): Promise { + static async slip10 (curve: string, S: string): Promise { const key = new TextEncoder().encode(curve) const data = new Uint8Array(64) data.set(S.match(/.{1,2}/g)!.map(byte => parseInt(byte, 16))) - const I = await hmac(key, data) + const I = await this.hmac(key, data) const IL = new DataView(I.buffer.slice(0, I.length / 2)) const IR = new DataView(I.buffer.slice(I.length / 2)) return ({ privateKey: IL, chainCode: IR }) } - async function CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise { + static async CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise { const key = new Uint8Array(chainCode.buffer) const data = new Uint8Array(37) data.set([0]) - data.set(ser256(privateKey), 1) - data.set(ser32(index), 33) - const I = await hmac(key, data) + data.set(this.ser256(privateKey), 1) + data.set(this.ser32(index), 33) + const I = await this.hmac(key, data) const IL = new DataView(I.buffer.slice(0, I.length / 2)) const IR = new DataView(I.buffer.slice(I.length / 2)) return ({ privateKey: IL, chainCode: IR }) } - function ser32 (integer: number): Uint8Array { + static ser32 (integer: number): Uint8Array { if (typeof integer !== 'number') { throw new TypeError(`Expected a number, received ${typeof integer}`) } @@ -103,7 +102,7 @@ const b = () => { return new Uint8Array(view.buffer) } - function ser256 (integer: DataView): Uint8Array { + static ser256 (integer: DataView): Uint8Array { if (integer.constructor !== DataView) { throw new TypeError(`Expected DataView, received ${typeof integer}`) } @@ -113,18 +112,12 @@ const b = () => { return new Uint8Array(integer.buffer) } - async function hmac (key: Uint8Array, data: Uint8Array): Promise { + static async hmac (key: Uint8Array, data: Uint8Array): Promise { const { subtle } = globalThis.crypto const pk = await subtle.importKey('raw', key, { name: 'HMAC', hash: 'SHA-512' }, false, ['sign']) const signature = await subtle.sign('HMAC', pk, data) return new Uint8Array(signature) } - - return { ckd, nanoCKD } } -export const Bip44Ckd = b() - -const start = b.toString().indexOf('{') + 1 -const end = b.toString().lastIndexOf('return') -export const worker = b.toString().substring(start, end) +export default Bip44Ckd.toString() -- 2.34.1