]> zoso.dev Git - libnemo.git/commitdiff
Exporting import.meta.url does not work since once it is bundled, all files share...
authorChris Duncan <chris@zoso.dev>
Tue, 26 Nov 2024 19:14:46 +0000 (11:14 -0800)
committerChris Duncan <chris@zoso.dev>
Tue, 26 Nov 2024 19:14:46 +0000 (11:14 -0800)
src/lib/pool.ts
src/lib/wallet.ts
src/lib/workers/ckdBip44.ts
src/lib/workers/ckdBlake2b.ts

index 0c3f9fd6b7138d62945f6507419e88ed65d96b43..6b86516cfc6bea385608766237ed98f706e4afd1 100644 (file)
@@ -32,7 +32,8 @@ export class Pool {
                return true
        }
 
-       constructor (url: string) {
+       constructor (fn: string) {
+               const url = URL.createObjectURL(new Blob([fn], { type: 'text/javascript' }))
                for (let i = navigator.hardwareConcurrency - 1; i > 0; i--) {
                        const thread = {
                                isBusy: false,
index e0e553b8481709a059fdb7c4f36f4e9be31bcb5c..afa02be9354de79926c04b61fe23410ac75dcb35 100644 (file)
@@ -572,7 +572,7 @@ export class Blake2bWallet extends Wallet {
        async ckd (index: number | number[]): Promise<Account[]> {\r
                if (!Array.isArray(index)) index = [index]\r
                const data: any = []\r
-               index.forEach(i => data.push({ seed: this.seed, index: i }))\r
+               index.forEach(i => data.push({ blake2b: blake2b.toString(), index: i, seed: this.seed }))\r
                const results: [{ index: number, key: string }] = await this.#pool.work(data)\r
                const accounts = []\r
                for (const result of results) {\r
index 95b3b9b930863b5175c5e64dd6ce53811716a8bd..7eaf9c10296fa85f9bcfe7e3d2cb5463ef5a22f9 100644 (file)
@@ -6,91 +6,94 @@ type ExtendedKey = {
        chainCode: DataView
 }
 
-const BIP44_COIN_NANO = 165
-const BIP44_PURPOSE = 44
-const HARDENED_OFFSET = 0x80000000
-const SLIP10_ED25519 = 'ed25519 seed'
+async function fn () {
+       const BIP44_COIN_NANO = 165
+       const BIP44_PURPOSE = 44
+       const HARDENED_OFFSET = 0x80000000
+       const SLIP10_ED25519 = 'ed25519 seed'
 
-/**
-* Listens for messages from a calling function.
-*/
-addEventListener('message', (message) => {
-       const { seed, index } = message.data ?? message
-       nanoCKD(seed, index).then(key => postMessage({ index, key }))
-})
+       /**
+       * Listens for messages from a calling function.
+       */
+       addEventListener('message', (message) => {
+               const { seed, index } = message.data ?? message
+               nanoCKD(seed, index).then(key => postMessage({ index, key }))
+       })
 
-/**
-* Derives a private child key following the BIP-32 and BIP-44 derivation path
-* registered to the Nano block lattice. Only hardened child keys are defined.
-*
-* @param {string} seed - Hexadecimal seed derived from mnemonic phrase
-* @param {number} index - Account number between 0 and 2^31-1
-* @returns Private child key for the account
-*/
-async function nanoCKD (seed: string, index: number): Promise<string> {
-       if (seed.length < 32 || seed.length > 128) {
-               throw new RangeError(`Invalid seed length`)
+       /**
+       * Derives a private child key following the BIP-32 and BIP-44 derivation path
+       * registered to the Nano block lattice. Only hardened child keys are defined.
+       *
+       * @param {string} seed - Hexadecimal seed derived from mnemonic phrase
+       * @param {number} index - Account number between 0 and 2^31-1
+       * @returns Private child key for the account
+       */
+       async function nanoCKD (seed: string, index: number): Promise<string> {
+               console.log(`seed: ${seed}; index: ${index}`)
+               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, BIP44_COIN_NANO + HARDENED_OFFSET)
+               const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET)
+               const privateKey = new Uint8Array(accountKey.privateKey.buffer)
+               return privateKey.reduce((key, byte) => key.concat(byte.toString(16).padStart(2, '0')), '')
        }
-       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, BIP44_COIN_NANO + HARDENED_OFFSET)
-       const accountKey = await CKDpriv(coinKey, index + HARDENED_OFFSET)
-       const privateKey = new Uint8Array(accountKey.privateKey.buffer)
-       return privateKey.reduce((key, byte) => key.concat(byte.toString(16).padStart(2, '0')), '')
-}
-
-async function slip10 (curve: string, S: string): Promise<ExtendedKey> {
-       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 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<ExtendedKey> {
-       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)
-       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 {
-       if (typeof integer !== 'number') {
-               throw new TypeError(`Expected a number, received ${typeof integer}`)
+       async function slip10 (curve: string, S: string): Promise<ExtendedKey> {
+               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 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 })
        }
-       if (integer > 0xffffffff) {
-               throw new RangeError(`Expected 32-bit integer, received ${integer.toString(2).length}-bit value: ${integer}`)
+
+       async function CKDpriv ({ privateKey, chainCode }: ExtendedKey, index: number): Promise<ExtendedKey> {
+               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)
+               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 })
        }
-       const view = new DataView(new ArrayBuffer(4))
-       view.setUint32(0, integer, false)
-       return new Uint8Array(view.buffer)
-}
 
-function ser256 (integer: DataView): Uint8Array {
-       if (integer.constructor !== DataView) {
-               throw new TypeError(`Expected DataView, received ${typeof integer}`)
+       function ser32 (integer: number): Uint8Array {
+               if (typeof integer !== 'number') {
+                       throw new TypeError(`Expected a number, received ${typeof integer}`)
+               }
+               if (integer > 0xffffffff) {
+                       throw new RangeError(`Expected 32-bit integer, received ${integer.toString(2).length}-bit value: ${integer}`)
+               }
+               const view = new DataView(new ArrayBuffer(4))
+               view.setUint32(0, integer, false)
+               return new Uint8Array(view.buffer)
        }
-       if (integer.byteLength > 32) {
-               throw new RangeError(`Expected 32-byte integer, received ${integer.byteLength}-byte value: ${integer}`)
+
+       function ser256 (integer: DataView): Uint8Array {
+               if (integer.constructor !== DataView) {
+                       throw new TypeError(`Expected DataView, received ${typeof integer}`)
+               }
+               if (integer.byteLength > 32) {
+                       throw new RangeError(`Expected 32-byte integer, received ${integer.byteLength}-byte value: ${integer}`)
+               }
+               return new Uint8Array(integer.buffer)
        }
-       return new Uint8Array(integer.buffer)
-}
 
-async function hmac (key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
-       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)
+       async function hmac (key: Uint8Array, data: Uint8Array): Promise<Uint8Array> {
+               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)
+       }
 }
 
-export default import.meta.url
+export default `(${fn.toString()})()`
index 6f27858f104409f9c8d823ba00851aed408f33cd..edb5b8316abbb13d10d9e88eadad0ee254819425 100644 (file)
@@ -1,29 +1,31 @@
 // SPDX-FileCopyrightText: 2024 Chris Duncan <chris@zoso.dev>
 // SPDX-License-Identifier: GPL-3.0-or-later
 
-import blake2b from 'blake2b'
+async function fn () {
+       /**
+       * Listens for messages from a calling function.
+       */
+       addEventListener('message', (message) => {
+               const { seed, index, blake2b } = message.data ?? message
+               ckdBlake2b(seed, index, blake2b).then(key => postMessage({ index, key }))
+       })
 
-/**
-* Listens for messages from a calling function.
-*/
-addEventListener('message', (message) => {
-       const { seed, index } = message.data ?? message
-       ckdBlake2b(seed, index).then(key => postMessage({ index, key }))
-})
-
-/**
-* Derives BLAKE2b account private keys.
-*
-* @param {number} index - Index of the account
-* @returns {Promise<string>}
-*/
-async function ckdBlake2b (seed: string, index: number): Promise<string> {
-       const indexHex = index.toString(16).padStart(8, '0').toUpperCase()
-       const inputHex = `${seed}${indexHex}`.padStart(72, '0')
-       const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16))
-       const inputBytes = Uint8Array.from(inputArray)
-       const hash = blake2b(32).update(inputBytes).digest('hex')
-       return hash
+       /**
+       * Derives BLAKE2b account private keys.
+       *
+       * @param {number} index - Index of the account
+       * @returns {Promise<string>}
+       */
+       async function ckdBlake2b (seed: string, index: number, blake2b: string): Promise<string> {
+               const blake = Function(`return ${blake2b}`)
+               console.log(blake)
+               const indexHex = index.toString(16).padStart(8, '0').toUpperCase()
+               const inputHex = `${seed}${indexHex}`.padStart(72, '0')
+               const inputArray = (inputHex.match(/.{1,2}/g) ?? []).map(h => parseInt(h, 16))
+               const inputBytes = Uint8Array.from(inputArray)
+               const hash = blake(32).update(inputBytes).digest('hex')
+               return hash
+       }
 }
 
-export default import.meta.url
+export default `(${fn.toString()})()`