From: Chris Duncan Date: Mon, 6 Jul 2026 06:27:08 +0000 (-0700) Subject: Fix recursive imports and use convert modules instead of tools modules for text codec. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=5cc0ffc99bba3315ff998c209263103d87011a57;p=libnemo.git Fix recursive imports and use convert modules instead of tools modules for text codec. --- diff --git a/src/lib/convert/bytes.ts b/src/lib/convert/bytes.ts index 3ff0855..cb29382 100644 --- a/src/lib/convert/bytes.ts +++ b/src/lib/convert/bytes.ts @@ -2,7 +2,8 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import { ALPHABET, HEXCHAR } from '../constants' -import { decode } from '../tools' + +const decoder = Object.freeze(new TextDecoder()) export const bytes = Object.freeze({ /** @@ -104,6 +105,6 @@ export const bytes = Object.freeze({ * @returns {string} UTF-8 encoded text string */ toUtf8 (bytes: Bytes): string { - return decode(bytes) + return decoder.decode(bytes) }, }) diff --git a/src/lib/convert/utf8.ts b/src/lib/convert/utf8.ts index 2223be4..2bbb96d 100644 --- a/src/lib/convert/utf8.ts +++ b/src/lib/convert/utf8.ts @@ -1,9 +1,10 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { encode } from '../tools' import { bytes } from './bytes' +const encoder = Object.freeze(new TextEncoder()) + export const utf8 = Object.freeze({ /** * Convert a UTF-8 text string to an ArrayBuffer. @@ -22,7 +23,7 @@ export const utf8 = Object.freeze({ * @returns {Uint8Array} Byte array representation of the input string */ toBytes (utf8: string): Bytes { - return encode(utf8) + return encoder.encode(utf8) }, /** diff --git a/src/lib/crypto/bip39.ts b/src/lib/crypto/bip39.ts index 19e2c0f..91e0b6b 100644 --- a/src/lib/crypto/bip39.ts +++ b/src/lib/crypto/bip39.ts @@ -1,8 +1,7 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { bytes } from '../convert' -import { encode } from '../tools' +import { bytes, utf8 } from '../convert' import { wordlist } from './wordlist' /** @@ -194,13 +193,13 @@ export class Bip39 { return Promise.resolve(seed) } else { const salt = (typeof passphrase === 'string') ? passphrase : '' - const keyData = encode(this.phrase) + const keyData = utf8.toBuffer(this.phrase) return crypto.subtle.importKey('raw', keyData, 'PBKDF2', false, ['deriveBits', 'deriveKey']) .then(phraseKey => { const algorithm: Pbkdf2Params = { name: 'PBKDF2', hash: 'SHA-512', - salt: encode(`mnemonic${salt.normalize('NFKD')}`), + salt: utf8.toBuffer(`mnemonic${salt.normalize('NFKD')}`), iterations: 2048 } return crypto.subtle.deriveBits(algorithm, phraseKey, 512) diff --git a/src/lib/crypto/bip44.ts b/src/lib/crypto/bip44.ts index 11de053..954f3f3 100644 --- a/src/lib/crypto/bip44.ts +++ b/src/lib/crypto/bip44.ts @@ -2,8 +2,7 @@ //! SPDX-License-Identifier: GPL-3.0-or-later import { Point, getPublicKey as secp256k1_getPublicKey } from '@noble/secp256k1' -import { dec } from '../convert' -import { encode } from '../tools' +import { dec, utf8 } from '../convert' type Curve = 'Bitcoin seed' | 'ed25519 seed' type ExtendedKey = { @@ -76,7 +75,7 @@ function ckd (curve: Curve, seed: ArrayBuffer, coin: number, account: number, ch } function slip10 (curve: string, S: ArrayBuffer): Promise { - const key = encode(curve).buffer + const key = utf8.toBuffer(curve) const data = S return hmac(key, data) .then(I => { diff --git a/src/lib/crypto/wallet-aes-gcm.ts b/src/lib/crypto/wallet-aes-gcm.ts index 7a3869d..1fcca16 100644 --- a/src/lib/crypto/wallet-aes-gcm.ts +++ b/src/lib/crypto/wallet-aes-gcm.ts @@ -3,11 +3,12 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later -import { encode } from "../tools" +import { utf8 } from "../convert" + export class WalletAesGcm { static decrypt (type: string, key: CryptoKey, iv: ArrayBuffer, encrypted: ArrayBuffer): Promise> { const seedLength = type === 'BLAKE2b' ? 32 : 64 - const additionalData = encode(type) + const additionalData = utf8.toBuffer(type) return crypto.subtle .decrypt({ name: 'AES-GCM', iv, additionalData }, key, encrypted) .then(decrypted => { @@ -30,7 +31,7 @@ export class WalletAesGcm { } // restrict iv to 96 bits per GCM best practice const iv = crypto.getRandomValues(new Uint8Array(12)).buffer - const additionalData = encode(type) + const additionalData = utf8.toBuffer(type) const encoded = new Uint8Array([...new Uint8Array(seed), ...new Uint8Array(mnemonic ?? [])]) return crypto.subtle .encrypt({ name: 'AES-GCM', iv, additionalData }, key, encoded) diff --git a/src/lib/ledger/open.ts b/src/lib/ledger/open.ts index 59edc68..7198ed7 100644 --- a/src/lib/ledger/open.ts +++ b/src/lib/ledger/open.ts @@ -3,11 +3,10 @@ import { TransportStatusError } from '@ledgerhq/errors' import { APDU_CODES, LISTEN_TIMEOUT, LedgerResponse, LedgerTransport, OPEN_TIMEOUT, STATUS_CODES } from '.' -import { bytes } from '../convert' -import { encode } from '../tools' +import { bytes, utf8 } from '../convert' export async function _open (transport: LedgerTransport): Promise { - const name = encode('Nano') + const name = utf8.toBytes('Nano') const t = await transport.create(OPEN_TIMEOUT, LISTEN_TIMEOUT) const response = await t .send(0xe0, 0xd8, APDU_CODES.paramUnused, APDU_CODES.paramUnused, name as Buffer) diff --git a/src/lib/tools.ts b/src/lib/tools.ts index 4470314..9c8e28e 100644 --- a/src/lib/tools.ts +++ b/src/lib/tools.ts @@ -15,27 +15,6 @@ type SweepResult = { message: string } -/** - * Decodes bytes to a UTF-8 string. - * - * @param {AllowSharedBufferSource} [input] - * @param {TextDecodeOptions} [options] - * @returns {string} Decoded string - */ -export function decode (input?: AllowSharedBufferSource, options?: TextDecodeOptions): string { - return decoder.decode(input, options) -} - -/** - * Encodes a UTF-8 string to bytes. - * - * @param {string} [input] - * @returns {Bytes} Encoded bytes - */ -export function encode (input?: string): Bytes { - return encoder.encode(input) -} - /** * Converts a decimal amount of nano from one unit divider to another. * @@ -229,6 +208,3 @@ function normalize (input: string | ArrayBuffer | Bytes): Bytes { ? new Uint8Array(input.slice()) : input } - -const decoder = Object.freeze(new TextDecoder()) -const encoder = Object.freeze(new TextEncoder()) diff --git a/src/lib/vault/vault-worker.ts b/src/lib/vault/vault-worker.ts index 514471a..ede1fae 100644 --- a/src/lib/vault/vault-worker.ts +++ b/src/lib/vault/vault-worker.ts @@ -4,9 +4,8 @@ import { derive as nano25519_derive, sign as nano25519_sign } from 'nano25519/sync' import { parentPort, threadId } from 'node:worker_threads' import { BIP44_COIN_NANO } from '../constants' -import { dec } from '../convert' +import { dec, utf8 } from '../convert' import { Bip39, Bip44, Blake2b, WalletAesGcm } from '../crypto' -import { encode } from '../tools' import { WalletType } from '../wallet' import { parseAction, parseData, parseIv, parseKeySalt, parseType } from './parsers' import { Passkey } from './passkey' @@ -365,7 +364,7 @@ function verify (seed?: ArrayBuffer, mnemonicPhrase?: string): Promise { - _mnemonic = new Uint8Array(encode(bip39.phrase ?? '')).buffer + _mnemonic = utf8.toBuffer(bip39.phrase ?? '') return secret }) } else { @@ -479,7 +478,7 @@ function _load (type?: 'BIP-44' | 'BLAKE2b' | 'Exodus', key?: CryptoKey, keySalt } else { seed = Bip39.fromPhrase(secret) .then(bip39 => { - _mnemonic = new Uint8Array(encode(bip39.phrase ?? '')).buffer + _mnemonic = utf8.toBuffer(bip39.phrase ?? '') const derive = type === 'BLAKE2b' ? Promise.resolve(bip39.toBlake2bSeed()) : bip39.toBip39Seed(mnemonicSalt ?? '')