From: Chris Duncan Date: Wed, 1 Jul 2026 05:53:39 +0000 (-0700) Subject: Extract static blake consts outside of class and implement type guard for byte arrays. X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=2236454ff319b5358222bea5f644cf6ef222f50a;p=libnemo.git Extract static blake consts outside of class and implement type guard for byte arrays. --- diff --git a/src/lib/crypto/blake2b.ts b/src/lib/crypto/blake2b.ts index d407199..b51feb4 100644 --- a/src/lib/crypto/blake2b.ts +++ b/src/lib/crypto/blake2b.ts @@ -1,6 +1,41 @@ //! SPDX-FileCopyrightText: 2025 Chris Duncan //! SPDX-License-Identifier: GPL-3.0-or-later AND ISC +const OUTBYTES_MIN = 1 +const OUTBYTES_MAX = 64 +const KEYBYTES_MIN = 1 +const KEYBYTES_MAX = 64 +const SALTBYTES = 16 +const PERSONALBYTES = 16 +const IV: bigint[] = [ + 0x6a09e667f3bcc908n, + 0xbb67ae8584caa73bn, + 0x3c6ef372fe94f82bn, + 0xa54ff53a5f1d36f1n, + 0x510e527fade682d1n, + 0x9b05688c2b3e6c1fn, + 0x1f83d9abfb41bd6bn, + 0x5be0cd19137e2179n +] +const SIGMA: number[][] = [ + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], + [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], + [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], + [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], + [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], + [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], + [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], + [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], + [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], + [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3] +] + +function isBytes (a: unknown): a is Bytes { + return a instanceof Uint8Array && a.buffer instanceof ArrayBuffer && a.byteLength > 0 +} + /** * Implementation derived from blake2b@2.1.4. Copyright 2017 Emil Bay * (https://github.com/emilbayes/blake2b). See LICENSES/ISC.txt @@ -33,57 +68,14 @@ export class Blake2b { return Promise.resolve(sk.buffer) } - /** @returns {1} */ - static get OUTBYTES_MIN (): 1 { return 1 } - /** @returns {64} */ - static get OUTBYTES_MAX (): 64 { return 64 } - /** @returns {1} */ - static get KEYBYTES_MIN (): 1 { return 1 } - /** @returns {64} */ - static get KEYBYTES_MAX (): 64 { return 64 } - /** @returns {16} */ - static get SALTBYTES (): 16 { return 16 } - /** @returns {16} */ - static get PERSONALBYTES (): 16 { return 16 } - /** @returns {bigint[]} */ - static get IV (): bigint[] { - return [ - 0x6a09e667f3bcc908n, - 0xbb67ae8584caa73bn, - 0x3c6ef372fe94f82bn, - 0xa54ff53a5f1d36f1n, - 0x510e527fade682d1n, - 0x9b05688c2b3e6c1fn, - 0x1f83d9abfb41bd6bn, - 0x5be0cd19137e2179n - ] - } - /** @returns {number[][]} */ - static get SIGMA (): number[][] { - return [ - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], - [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], - [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], - [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], - [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], - [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], - [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], - [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], - [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], - [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], - [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3] - ] - } - #G (r: number, i: number, a: number, b: number, c: number, d: number): void { - this.#v[a] += this.#v[b] + this.#m[(this.constructor as typeof Blake2b).SIGMA[r][i << 1]] + this.#v[a] += this.#v[b] + this.#m[SIGMA[r][i << 1]] this.#v[d] ^= this.#v[a] this.#v[d] = (this.#v[d] >> 32n) | (this.#v[d] << 32n) this.#v[c] += this.#v[d] this.#v[b] ^= this.#v[c] this.#v[b] = (this.#v[b] >> 24n) | (this.#v[b] << 40n) - this.#v[a] += this.#v[b] + this.#m[(this.constructor as typeof Blake2b).SIGMA[r][(i << 1) + 1]] + this.#v[a] += this.#v[b] + this.#m[SIGMA[r][(i << 1) + 1]] this.#v[d] ^= this.#v[a] this.#v[d] = (this.#v[d] >> 16n) | (this.#v[d] << 48n) this.#v[c] += this.#v[d] @@ -117,7 +109,7 @@ export class Blake2b { // initialize hash state for (let i = 0; i < 8; i++) { - this.#h[i] = Blake2b.IV[i] ^ this.#parameter_view.getBigUint64(i << 3, true) + this.#h[i] = IV[i] ^ this.#parameter_view.getBigUint64(i << 3, true) } // key the hash, if applicable @@ -139,7 +131,7 @@ export class Blake2b { // init work variables for (let i = 0; i < 8; i++) { this.#v[i] = this.#h[i] - this.#v[i + 8] = (this.constructor as typeof Blake2b).IV[i] + this.#v[i + 8] = IV[i] } // lo 64 bits of counter @@ -244,38 +236,37 @@ export class Blake2b { */ constructor (length: number, key?: Bytes, salt?: Bytes, personal?: Bytes) constructor (length: unknown, key?: unknown, salt?: unknown, personal?: unknown) { - const B = this.constructor as typeof Blake2b if (length == null) { throw new TypeError(`length is required`) } if (typeof length !== 'number') { throw new TypeError(`length must be number`) } - if (length < B.OUTBYTES_MIN || length > B.OUTBYTES_MAX) { - throw new RangeError(`length must be ${B.OUTBYTES_MIN}-${B.OUTBYTES_MAX} bytes`) + if (length < OUTBYTES_MIN || length > OUTBYTES_MAX) { + throw new RangeError(`length must be ${OUTBYTES_MIN}-${OUTBYTES_MAX} bytes`) } if (key !== undefined) { - if (!(key instanceof Uint8Array)) { + if (!isBytes(key)) { throw new TypeError(`key must be Uint8Array or Buffer`) } - if (key.length < B.KEYBYTES_MIN || key.length > B.KEYBYTES_MAX) { - throw new RangeError(`key must be ${B.KEYBYTES_MIN}-${B.KEYBYTES_MAX} bytes`) + if (key.length < KEYBYTES_MIN || key.length > KEYBYTES_MAX) { + throw new RangeError(`key must be ${KEYBYTES_MIN}-${KEYBYTES_MAX} bytes`) } } if (salt !== undefined) { - if (!(salt instanceof Uint8Array)) { + if (!isBytes(salt)) { throw new TypeError(`salt must be Uint8Array or Buffer`) } - if (salt.length !== B.SALTBYTES) { - throw new RangeError(`salt must be ${B.SALTBYTES} bytes`) + if (salt.length !== SALTBYTES) { + throw new RangeError(`salt must be ${SALTBYTES} bytes`) } } if (personal !== undefined) { - if (!(personal instanceof Uint8Array)) { + if (!isBytes(personal)) { throw new TypeError(`personal must be Uint8Array or Buffer`) } - if (personal.length !== B.PERSONALBYTES) { - throw new RangeError(`personal must be ${B.PERSONALBYTES} bytes`) + if (personal.length !== PERSONALBYTES) { + throw new RangeError(`personal must be ${PERSONALBYTES} bytes`) } } this.#blake2bInit(length, key, salt, personal)