From dddf7c5b1328d3c03abb0eb4de7987f2374f3c6c Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Tue, 26 Nov 2024 17:03:53 -0800 Subject: [PATCH] Save changes. --- src/lib/account.ts | 2 +- src/lib/blake2b.ts | 155 +++++++++++++++++----------------- src/lib/wallet.ts | 3 +- src/lib/workers/ckdBlake2b.ts | 11 ++- 4 files changed, 87 insertions(+), 84 deletions(-) diff --git a/src/lib/account.ts b/src/lib/account.ts index 9ad147b..143543d 100644 --- a/src/lib/account.ts +++ b/src/lib/account.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later -import blake2b from 'blake2b' +import blake2b from './blake2b.js' import { ACCOUNT_KEY_LENGTH, ALPHABET, PREFIX, PREFIX_LEGACY } from './constants.js' import { base32, bytes, hex } from './convert.js' import { Rpc } from './rpc.js' diff --git a/src/lib/blake2b.ts b/src/lib/blake2b.ts index 81fe42a..e63ae27 100644 --- a/src/lib/blake2b.ts +++ b/src/lib/blake2b.ts @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later - +//@ts-nocheck 'use strict' /** @@ -13,19 +13,89 @@ * TypeScript, and bundle into web workers. * Original source commit: https://github.com/emilbayes/blake2b/blob/1f63e02e3f226642959506cdaa67c8819ff145cd/index.js */ -const BYTES_MIN = 16 -const BYTES_MAX = 64 -const KEYBYTES_MIN = 16 -const KEYBYTES_MAX = 64 -const SALTBYTES = 16 -const PERSONALBYTES = 16 +export default class Blake2b { + const BYTES_MIN = 16 + const BYTES_MAX = 64 + const KEYBYTES_MIN = 16 + const KEYBYTES_MAX = 64 + const SALTBYTES = 16 + const PERSONALBYTES = 16 + + constructor (outlen: number, key?: Uint8Array, salt?: Uint8Array, personal?: Uint8Array, noAssert?: boolean) { + if (noAssert !== true) { + if (outlen < BYTES_MIN) + throw new RangeError(`outlen must be at least ${BYTES_MIN}, was given ${outlen}`) + if (outlen > BYTES_MAX) + throw new RangeError(`outlen must be at most ${BYTES_MAX}, was given ${outlen}`) + if (key != null) { + if (!(key instanceof Uint8Array)) + throw new TypeError(`key must be Uint8Array or Buffer`) + if (key.length < KEYBYTES_MIN) + throw new RangeError(`key must be at least ${KEYBYTES_MIN}, was given ${key.length}`) + if (key.length > KEYBYTES_MAX) + throw new RangeError(`key must be at most ${KEYBYTES_MAX}, was given ${key.length}`) + } + if (salt != null) { + if (!(salt instanceof Uint8Array)) + throw new TypeError(`salt must be Uint8Array or Buffer`) + if (salt.length !== SALTBYTES) + throw new RangeError(`salt must be exactly ${SALTBYTES}, was given ${salt.length}`) + } + if (personal != null) { + if (!(personal instanceof Uint8Array)) + throw new TypeError(`personal must be Uint8Array or Buffer`) + if (personal.length !== PERSONALBYTES) + throw new RangeError(`personal must be exactly ${PERSONALBYTES}, was given ${personal.length}`) + } + } + + return this.create(outlen, key, salt, personal) + } + +/** +* Creates a BLAKE2b hashing context +* Requires an output length between 1 and 64 bytes +* Takes an optional Uint8Array key +*/ +function create (this: typeof Blake2b, outlen: number, key?: Uint8Array, salt?: Uint8Array, personal?: Uint8Array) { + // zero out parameter_block before usage + parameter_block.fill(0) + // state, 'param block' + + this.b = new Uint8Array(128) + this.h = new Uint32Array(16) + this.t = 0 // input count + this.c = 0 // pointer within buffer + this.outlen = outlen // output length in bytes + + parameter_block[0] = outlen + if (key) parameter_block[1] = key.length + parameter_block[2] = 1 // fanout + parameter_block[3] = 1 // depth + + if (salt) parameter_block.set(salt, 32) + if (personal) parameter_block.set(personal, 48) + + // initialize hash state + for (var i = 0; i < 16; i++) { + this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) + } + + // key the hash, if applicable + if (key) { + blake2bUpdate(this, key) + // at the end + this.c = 128 + } + return new this +} /** * 64-bit unsigned addition * Sets v[a,a+1] += v[b,b+1] * v should be a Uint32Array */ -function ADD64AA (v, a, b) { +function ADD64AA (v: Uint32Array, a, b) { var o0 = v[a] + v[b] var o1 = v[a + 1] + v[b + 1] if (o0 >= 0x100000000) { @@ -204,44 +274,7 @@ var parameter_block = new Uint8Array([ 0, 0, 0, 0 // 60: personal ]) -/** -* Creates a BLAKE2b hashing context -* Requires an output length between 1 and 64 bytes -* Takes an optional Uint8Array key -*/ -function Blake2b (outlen: number, key?: Uint8Array, salt?: Uint8Array, personal?: Uint8Array) { - // zero out parameter_block before usage - parameter_block.fill(0) - // state, 'param block' - - this.b = new Uint8Array(128) - this.h = new Uint32Array(16) - this.t = 0 // input count - this.c = 0 // pointer within buffer - this.outlen = outlen // output length in bytes - - parameter_block[0] = outlen - if (key) parameter_block[1] = key.length - parameter_block[2] = 1 // fanout - parameter_block[3] = 1 // depth - - if (salt) parameter_block.set(salt, 32) - if (personal) parameter_block.set(personal, 48) - - // initialize hash state - for (var i = 0; i < 16; i++) { - this.h[i] = BLAKE2B_IV32[i] ^ B2B_GET32(parameter_block, i * 4) - } - - // key the hash, if applicable - if (key) { - blake2bUpdate(this, key) - // at the end - this.c = 128 - } -} - -Blake2b.prototype.update = function (input: Uint8Array) { +static function update (input: Uint8Array) { if (!(input instanceof Uint8Array)) throw new TypeError(`input must be Uint8Array or Buffer`) blake2bUpdate(this, input) @@ -307,34 +340,4 @@ function toHex (n: number) { throw new RangeError(`expected byte value 0-255, received ${n}`) return n.toString(16).padStart(2, '0') } - -export default function createHash (outlen: number, key?: Uint8Array, salt?: Uint8Array, personal?: Uint8Array, noAssert?: boolean) { - if (noAssert !== true) { - if (outlen < BYTES_MIN) - throw new RangeError(`outlen must be at least ${BYTES_MIN}, was given ${outlen}`) - if (outlen > BYTES_MAX) - throw new RangeError(`outlen must be at most ${BYTES_MAX}, was given ${outlen}`) - if (key != null) { - if (!(key instanceof Uint8Array)) - throw new TypeError(`key must be Uint8Array or Buffer`) - if (key.length < KEYBYTES_MIN) - throw new RangeError(`key must be at least ${KEYBYTES_MIN}, was given ${key.length}`) - if (key.length > KEYBYTES_MAX) - throw new RangeError(`key must be at most ${KEYBYTES_MAX}, was given ${key.length}`) - } - if (salt != null) { - if (!(salt instanceof Uint8Array)) - throw new TypeError(`salt must be Uint8Array or Buffer`) - if (salt.length !== SALTBYTES) - throw new RangeError(`salt must be exactly ${SALTBYTES}, was given ${salt.length}`) - } - if (personal != null) { - if (!(personal instanceof Uint8Array)) - throw new TypeError(`personal must be Uint8Array or Buffer`) - if (personal.length !== PERSONALBYTES) - throw new RangeError(`personal must be exactly ${PERSONALBYTES}, was given ${personal.length}`) - } - } - - return new Blake2b(outlen, key, salt, personal) } diff --git a/src/lib/wallet.ts b/src/lib/wallet.ts index 6472738..5a69f6b 100644 --- a/src/lib/wallet.ts +++ b/src/lib/wallet.ts @@ -1,6 +1,7 @@ // SPDX-FileCopyrightText: 2024 Chris Duncan // SPDX-License-Identifier: GPL-3.0-or-later +import { fn } from './blake2b.js' import { ckdBip44, ckdBlake2b } from './workers.js' import { Account } from './account.js' import { Bip39Mnemonic } from './bip39-mnemonic.js' @@ -575,7 +576,7 @@ export class Blake2bWallet extends Wallet { async ckd (index: number | number[]): Promise { if (!Array.isArray(index)) index = [index] const data: any = [] - index.forEach(i => data.push({ blake2b: blake2b.toString(), index: i, seed: this.seed })) + index.forEach(i => data.push({ seed: this.seed, index: i, b2b: fn })) let now = performance.now() const results: [{ index: number, key: string }] = await this.#pool.work(data) console.log(`ckd: ${-now + (now = performance.now())} ms`) diff --git a/src/lib/workers/ckdBlake2b.ts b/src/lib/workers/ckdBlake2b.ts index edb5b83..ff5174d 100644 --- a/src/lib/workers/ckdBlake2b.ts +++ b/src/lib/workers/ckdBlake2b.ts @@ -6,8 +6,8 @@ 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 })) + const { seed, index, b2b } = message.data ?? message + ckdBlake2b(seed, index, b2b).then(key => postMessage({ index, key })) }) /** @@ -16,14 +16,13 @@ async function fn () { * @param {number} index - Index of the account * @returns {Promise} */ - async function ckdBlake2b (seed: string, index: number, blake2b: string): Promise { - const blake = Function(`return ${blake2b}`) - console.log(blake) + async function ckdBlake2b (seed: string, index: number, b2b: string): Promise { + const blake2b = Function(b2b) 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') + const hash = blake2b(32).update(inputBytes).digest('hex') return hash } } -- 2.34.1