From 6bb12ffb51a4c8516f623920c513651580bc2fca Mon Sep 17 00:00:00 2001 From: Chris Duncan Date: Thu, 2 Jul 2026 23:58:59 -0700 Subject: [PATCH] Use bitwise ops instead of arithmetic where possible. Build mnemonic phrase string directly instead of using intermediate array. --- src/lib/crypto/bip39.ts | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/lib/crypto/bip39.ts b/src/lib/crypto/bip39.ts index a00c755..37a5f26 100644 --- a/src/lib/crypto/bip39.ts +++ b/src/lib/crypto/bip39.ts @@ -17,7 +17,7 @@ export class Bip39 { * @returns {Promise} First N/32 bits of the hash as a bigint */ static checksum (entropy: ArrayBuffer | Bytes): Promise { - const checksumBitLength = (entropy.byteLength / 4) | 0 + const checksumBitLength = entropy.byteLength >> 2 return crypto.subtle.digest('SHA-256', entropy) .then(hash => { const sha256sum = new Uint8Array(hash)[0] @@ -46,25 +46,22 @@ export class Bip39 { if (entropy.byteLength < 16 || entropy.byteLength > 32) { throw new RangeError(`Entropy must be 16-32 bytes`) } - if (entropy.byteLength % 4 !== 0) { + if (entropy.byteLength & 3) { throw new RangeError(`Entropy must be a multiple of 4 bytes`) } - const phraseLength = 0.75 * entropy.byteLength + const phraseLength = (entropy.byteLength >> 2) * 3 return this.checksum(entropy) .then(checksum => { - const bigEntropy = bytes.toInt(entropy) - - let concatenation: bigint = (bigEntropy << BigInt(entropy.byteLength) / 4n) | checksum - const words: string[] = [] + let concatenation: bigint = (bytes.toInt(entropy) << BigInt(entropy.byteLength >> 2)) | checksum + let phrase = '' for (let i = 0; i < phraseLength; i++) { const wordBits = concatenation & 2047n const wordIndex = Number(wordBits) - words.unshift(wordlist[wordIndex]) + phrase = wordlist[wordIndex] + (i ? ' ' : '') + phrase concatenation >>= 11n } - const sentence = words.join(' ') - return this.fromPhrase(sentence) + return this.fromPhrase(phrase) }) } @@ -129,13 +126,13 @@ export class Bip39 { || entropyBits > (1n << 256n) - 1n || entropyLength < 128n || entropyLength > 256n - || Number(entropyLength) % 32 !== 0 + || Number(entropyLength & 31n) !== 0 ) { return Promise.resolve(false) } - const bytes = new Uint8Array(Number(entropyLength) / 8) + const bytes = new Uint8Array(Number(entropyLength >> 3n)) for (let i = 0; i < bytes.length; i++) { - const shift = entropyLength - (8n * BigInt(i + 1)) + const shift = entropyLength - (BigInt(i + 1) << 3n) const byte = (entropyBits >> shift) & 255n bytes[i] = Number(byte) } -- 2.52.0