]> git.codecow.com Git - nano25519.git/commitdiff
Restrict input to bytes only, no array buffers. Fix typings and test.
authorChris Duncan <chris@zoso.dev>
Sun, 27 Sep 2026 08:48:37 +0000 (01:48 -0700)
committerChris Duncan <chris@zoso.dev>
Sun, 27 Sep 2026 08:48:37 +0000 (01:48 -0700)
package.json
src/lib/primordials.ts
src/lib/wasm.ts
test/node.mjs

index 5e9d23efd228a71143e591acaf94d3a4947484ae..9ec3d1c6e9af53972a236e03bb0abe3e49c54802 100644 (file)
@@ -37,7 +37,7 @@
                "compile": "node scripts/blake2b-gen.mjs && asc ./src/assembly/index.ts && tsc",
                "prepublishOnly": "npm run test:prod",
                "test": "npm run build && npm run test:all",
-               "test:all": "npm run test:be && npm run test:le",
+               "test:all": "npm run test:le && npm run test:be",
                "test:be": "node --import ./test/big-endian.mjs ./test/node.mjs",
                "test:le": "node ./test/node.mjs",
                "test:prod": "npm run build:prod && npm run test:all"
index 101ff485aa165c43a24187d8f6a8690230ed9f98..bbfc930deb3d41e2a96fadfbd7ccbcf6982ccbdc 100644 (file)
@@ -207,19 +207,17 @@ export function normalize (name: string, byteLengthMin: number, byteLengthMax: n
                return hexToBytes(value)
        }
 
-       if (isArrayBuffer(value)) {
-               value = new Bytes(value)
-       }
-       if (!isBytes(value)) {
-               throw new TypeError(`${name} must be Uint8Array or ArrayBuffer`)
-       }
-       const bytes = copy(value)
-       const byteLength = getByteLength(bytes)
-       if (byteLength < byteLengthMin) {
-               throw new TypeError(`${name} must be at least ${byteLengthMin} bytes`)
-       }
-       if (byteLength > byteLengthMax) {
-               throw new TypeError(`${name} must be no more than ${byteLengthMax} bytes`)
+       if (isBytes(value)) {
+               const bytes = copy(value)
+               const byteLength = getByteLength(bytes)
+               if (byteLength < byteLengthMin) {
+                       throw new TypeError(`${name} must be at least ${byteLengthMin} bytes`)
+               }
+               if (byteLength > byteLengthMax) {
+                       throw new TypeError(`${name} must be no more than ${byteLengthMax} bytes`)
+               }
+               return bytes
        }
-       return bytes
+
+       throw new TypeError(`${name} must be a hex string or Uint8Array<ArrayBuffer>`)
 }
index cf14aafbd105db7556ba305cc11937b01728b693..d986d309e0b8eef8a7b93f1fb9dfbfc37f9b0d02 100644 (file)
@@ -19,28 +19,28 @@ type Exports = WebAssembly.Instance['exports'] & {
        getOutputDeriveByte: (index: number) => number
        getOutputSignByte: (index: number) => number
        getOutputVerifyByte: (index: number) => number
-       BLOCKHASH_BYTELENGTH: WebAssembly.Global
-       KEY_BYTELENGTH: WebAssembly.Global
-       SIGNATURE_BYTELENGTH: WebAssembly.Global
-       MAX_VERIFY_BLOCKS: WebAssembly.Global
-       MAX_VERIFY_BLOCKS_BYTELENGTH: WebAssembly.Global
-       MAX_MESSAGE_BYTELENGTH: WebAssembly.Global
-       BUFFER_INPUT_MSG: WebAssembly.Global
-       BUFFER_INPUT_PRV: WebAssembly.Global
-       BUFFER_INPUT_PUB: WebAssembly.Global
-       BUFFER_INPUT_SIG: WebAssembly.Global
-       BUFFER_OUTPUT_DERIVE: WebAssembly.Global
-       BUFFER_OUTPUT_SIGN: WebAssembly.Global
-       BUFFER_OUTPUT_VERIFY: WebAssembly.Global
-       ERROR_BYTE_OUT_OF_RANGE: WebAssembly.Global
-       ERROR_INDEX_OUT_OF_RANGE: WebAssembly.Global
-       ERROR_INVALID_BLOCK_COUNT: WebAssembly.Global
-       ERROR_INVALID_MESSAGE_LENGTH: WebAssembly.Global
-       ERROR_INVALID_PUBLIC_KEY: WebAssembly.Global
-       ERROR_SELFTEST_XFAIL_ONE: WebAssembly.Global
-       ERROR_SELFTEST_XFAIL_PAIR: WebAssembly.Global
-       ERROR_SELFTEST_XPASS: WebAssembly.Global
-       ERROR_UNKNOWN: WebAssembly.Global
+       BLOCKHASH_BYTELENGTH: WebAssembly.Global<'i32'>
+       KEY_BYTELENGTH: WebAssembly.Global<'i32'>
+       SIGNATURE_BYTELENGTH: WebAssembly.Global<'i32'>
+       MAX_VERIFY_BLOCKS: WebAssembly.Global<'i32'>
+       MAX_VERIFY_BLOCKS_BYTELENGTH: WebAssembly.Global<'i32'>
+       MAX_MESSAGE_BYTELENGTH: WebAssembly.Global<'i32'>
+       BUFFER_INPUT_MSG: WebAssembly.Global<'i32'>
+       BUFFER_INPUT_PRV: WebAssembly.Global<'i32'>
+       BUFFER_INPUT_PUB: WebAssembly.Global<'i32'>
+       BUFFER_INPUT_SIG: WebAssembly.Global<'i32'>
+       BUFFER_OUTPUT_DERIVE: WebAssembly.Global<'i32'>
+       BUFFER_OUTPUT_SIGN: WebAssembly.Global<'i32'>
+       BUFFER_OUTPUT_VERIFY: WebAssembly.Global<'i32'>
+       ERROR_BYTE_OUT_OF_RANGE: WebAssembly.Global<'i32'>
+       ERROR_INDEX_OUT_OF_RANGE: WebAssembly.Global<'i32'>
+       ERROR_INVALID_BLOCK_COUNT: WebAssembly.Global<'i32'>
+       ERROR_INVALID_MESSAGE_LENGTH: WebAssembly.Global<'i32'>
+       ERROR_INVALID_PUBLIC_KEY: WebAssembly.Global<'i32'>
+       ERROR_SELFTEST_XFAIL_ONE: WebAssembly.Global<'i32'>
+       ERROR_SELFTEST_XFAIL_PAIR: WebAssembly.Global<'i32'>
+       ERROR_SELFTEST_XPASS: WebAssembly.Global<'i32'>
+       ERROR_UNKNOWN: WebAssembly.Global<'i32'>
 }
 
 let locked = false
index b37e4597473b791e8fb3cafdceddd10db29bc21b..1a9e965d3136e9bb3236ca9142c6d179c619b951 100644 (file)
@@ -116,7 +116,7 @@ try {
        result = false
 } catch (err) {
        if (err != null && typeof err === 'object' && 'message' in err) {
-               result = err.message === `private key must be Uint8Array or ArrayBuffer`
+               result = err.message === `private key must be a hex string or Uint8Array<ArrayBuffer>`
        } else {
                result = false
        }
@@ -134,7 +134,7 @@ try {
        result = false
 } catch (err) {
        if (err != null && typeof err === 'object' && 'message' in err) {
-               result = err.message === `private key must be Uint8Array or ArrayBuffer`
+               result = err.message === `private key must be a hex string or Uint8Array<ArrayBuffer>`
        } else {
                result = false
        }
@@ -410,6 +410,7 @@ for (const { privateKey, publicKey, message, signature } of PYTHON_ED25519_BLAKE
  */
 function sweepMessage (length, flips) {
        const message = new Uint8Array(length).map((_, i) => (i * 37 + 11) & 255)
+       /** @type {{ byte: number, mask: string, result: unknown }[]} */
        const missed = []
        let signature
        try {
@@ -425,7 +426,7 @@ function sweepMessage (length, flips) {
                try {
                        result = verify(signature, message, NANO_ORG_VECTOR.publicKeyBytes)
                } catch (err) {
-                       result = `threw ${err?.message}`
+                       result = `threw ${typeof err === 'object' && err != null && 'message' in err ? err?.message : err}`
                }
                message[i] ^= mask
                if (result !== false) {
@@ -435,8 +436,10 @@ function sweepMessage (length, flips) {
        return { baseline: true, missed }
 }
 
+/** @type {[number, (length: number) => [number, number][]][]} */
 const sweeps = [
        [constants.MAX_MESSAGE_BYTELENGTH, (length) => {
+               /** @type {[number, number][]} */
                const flips = []
                for (let chunk = 0; chunk < length >> 5; chunk++) {
                        flips.push([(chunk << 5) + (chunk & 31), 1 << ((chunk >> 5) & 7)])
@@ -444,6 +447,7 @@ const sweeps = [
                return flips
        }],
        [constants.MAX_MESSAGE_BYTELENGTH - 1, (length) => {
+               /** @type {[number, number][]} */
                const flips = []
                for (let i = (length & ~31) - 32; i < length; i++) {
                        flips.push([i, 1 << (i & 7)])