]> git.codecow.com Git - libnemo.git/commitdiff
Extract static blake consts outside of class and implement type guard for byte arrays.
authorChris Duncan <chris@codecow.com>
Wed, 1 Jul 2026 05:53:39 +0000 (22:53 -0700)
committerChris Duncan <chris@codecow.com>
Wed, 1 Jul 2026 05:53:39 +0000 (22:53 -0700)
src/lib/crypto/blake2b.ts

index d4071991db95d1a0f308126ae3ebbf0b0c88ed6b..b51feb4a88af5af0ecaa7fa5a618de8c3a846743 100644 (file)
@@ -1,6 +1,41 @@
 //! SPDX-FileCopyrightText: 2025 Chris Duncan <chris@codecow.com>
 //! 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
  * <github@tixz.dk> (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)