diff --git a/.github/workflows/deno.yml b/.github/workflows/deno.yml index fca5e2f..00a0efe 100644 --- a/.github/workflows/deno.yml +++ b/.github/workflows/deno.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - deno-version: [1.36.4] + deno-version: [1.40.5] steps: - name: checkout project diff --git a/.github/workflows/node.yml b/.github/workflows/node.yml index e1a05d5..4345ca9 100644 --- a/.github/workflows/node.yml +++ b/.github/workflows/node.yml @@ -17,7 +17,7 @@ jobs: strategy: matrix: deno-version: [1.36.4] - node-version: [20.x, 18.x] + node-version: [21.x] steps: - name: checkout nkeys diff --git a/modules/cjs/index.ts b/modules/cjs/index.ts index 0b00a93..97da766 100644 --- a/modules/cjs/index.ts +++ b/modules/cjs/index.ts @@ -12,6 +12,9 @@ const helper = { verify: nacl.sign.detached.verify, fromSeed: nacl.sign.keyPair.fromSeed, sign: nacl.sign.detached, + scalarBaseMultiply: nacl.scalarMult.base, + seal: nacl.box, + open: nacl.box.open, }; // This here to support node 10. diff --git a/modules/esm/deps.ts b/modules/esm/deps.ts index 086b2b2..8c87da5 100644 --- a/modules/esm/deps.ts +++ b/modules/esm/deps.ts @@ -35,4 +35,7 @@ export const denoHelper = { sign: nacl.sign.detached, verify: nacl.sign.detached.verify, randomBytes: nacl.randomBytes, + scalarBaseMultiply: nacl.scalarMult.base, + seal: nacl.box, + open: nacl.box.open, } as Ed25519Helper; diff --git a/node_test/basics_test.js b/node_test/basics_test.js index 9e62973..7fb4be5 100644 --- a/node_test/basics_test.js +++ b/node_test/basics_test.js @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -161,3 +161,150 @@ test("integration - encoded seed returns stable values albertor", (t) => { t.is(kp.getPublicKey(), data.public_key, "public key"); t.is(td.decode(kp.getPrivateKey()), data.private_key, "private key"); }); + +test("integration - curve encrypt", (t) => { + // this is actual data generated by the nkeys go library + const expected = [ + 120, + 107, + 118, + 49, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 103, + 188, + 195, + 73, + 0, + 3, + 119, + 91, + 181, + 167, + 162, + 167, + 105, + 51, + 102, + 84, + 94, + 152, + 189, + 229, + 149, + 222, + 47, + 17, + 149, + 188, + 170, + ]; + const secret = "SXAESVBNK3UN2O24Z53ZJLFMX5OYHLAAVULRILWXRO775SDYFKI7FM3J7Y"; + const recipient = + "SXAHMGVNIYUF4CA5G475EN64YWNG32HSIF4MZCPZHV7PAFYTWBE5J5USFE"; + + // parse the imported secret and public + const kp = fromSeed(new TextEncoder().encode(secret)); + const kp2 = fromSeed(new TextEncoder().encode(recipient)); + const pub2 = kp2.getPublicKey(); + + // nonce is 24 empty bytes for ease of inspection + const nonce = new Uint8Array(24); + const data = new TextEncoder().encode("hello world"); + + const enc = kp.seal(data, pub2, nonce); + t.deepEqual(enc, new Uint8Array(expected)); +}); + +test("integration - curve decrypt", (t) => { + // this is actual data generated by the nkeys go library + const message = [ + 120, + 107, + 118, + 49, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 103, + 188, + 195, + 73, + 0, + 3, + 119, + 91, + 181, + 167, + 162, + 167, + 105, + 51, + 102, + 84, + 94, + 152, + 189, + 229, + 149, + 222, + 47, + 17, + 149, + 188, + 170, + ]; + const sender = "SXAESVBNK3UN2O24Z53ZJLFMX5OYHLAAVULRILWXRO775SDYFKI7FM3J7Y"; + const secret = "SXAHMGVNIYUF4CA5G475EN64YWNG32HSIF4MZCPZHV7PAFYTWBE5J5USFE"; + + // parse the imported secret and public + const kp = fromSeed(new TextEncoder().encode(secret)); + const kp2 = fromSeed(new TextEncoder().encode(sender)); + const senderPK = kp2.getPublicKey(); + + const enc = kp.open(new Uint8Array(message), senderPK) ?? new Uint8Array(); + t.is(new TextDecoder().decode(enc), "hello world"); +}); diff --git a/package-lock.json b/package-lock.json index 491ff86..db3b202 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,26 +1,46 @@ { "name": "nkeys.js", - "version": "1.0.6-1", + "version": "1.1.0-1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "nkeys.js", - "version": "1.0.6-1", + "version": "1.1.0-1", "license": "Apache-2.0", "dependencies": { "tweetnacl": "1.0.3" }, "devDependencies": { - "@types/node": "^20.8.x", - "ava": "^5.2.x", - "typedoc": "^0.25.x", - "typescript": "^5.2.x" + "@types/node": "^20.11.x", + "ava": "^6.1.x", + "typedoc": "^0.25.8", + "typescript": "^5.3.3" }, "engines": { "node": ">=10.0.0" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -56,19 +76,88 @@ "node": ">= 8" } }, + "node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz", + "integrity": "sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@types/node": { - "version": "20.8.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.10.tgz", - "integrity": "sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==", + "version": "20.11.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.19.tgz", + "integrity": "sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==", "dev": true, "dependencies": { "undici-types": "~5.26.4" } }, + "node_modules/@vercel/nft": { + "version": "0.26.4", + "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.26.4.tgz", + "integrity": "sha512-j4jCOOXke2t8cHZCIxu1dzKLHLcFmYzC3yqAK6MfZznOL1QIJKd0xcFsXK3zcqzU7ScsE2zWkiMMNHGMHgp+FA==", + "dev": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.5", + "@rollup/pluginutils": "^4.0.0", + "acorn": "^8.6.0", + "acorn-import-attributes": "^1.9.2", + "async-sema": "^3.1.1", + "bindings": "^1.4.0", + "estree-walker": "2.0.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.2", + "node-gyp-build": "^4.2.2", + "resolve-from": "^5.0.0" + }, + "bin": { + "nft": "out/cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -77,29 +166,34 @@ "node": ">=0.4.0" } }, + "node_modules/acorn-import-attributes": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.2.tgz", + "integrity": "sha512-O+nfJwNolEA771IYJaiLWK1UAwjNsQmZbTRqqwBYxCgVQTmpFEMvBw6LOIQV0Me339L5UMVYFyRohGnGlQDdIQ==", + "dev": true, + "peerDependencies": { + "acorn": "^8" + } + }, "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", - "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { "node": ">=0.4.0" } }, - "node_modules/aggregate-error": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz", - "integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==", + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "dev": true, "dependencies": { - "clean-stack": "^4.0.0", - "indent-string": "^5.0.0" + "debug": "4" }, "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6.0.0" } }, "node_modules/ansi-regex": { @@ -132,17 +226,23 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "dev": true + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", "dev": true, "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" }, "engines": { - "node": ">= 8" + "node": ">=10" } }, "node_modules/argparse": { @@ -184,51 +284,54 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/async-sema": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", + "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", + "dev": true + }, "node_modules/ava": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/ava/-/ava-5.3.1.tgz", - "integrity": "sha512-Scv9a4gMOXB6+ni4toLuhAm9KYWEjsgBglJl+kMGI5+IVDt120CCDZyB5HNU9DjmLI2t4I0GbnxGLmmRfGTJGg==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/ava/-/ava-6.1.1.tgz", + "integrity": "sha512-A+DG0Ag0e5zvt262Ze0pG5QH7EBmhn+DB9uK7WkUtJVAtGjZFeKTpUOKx339DMGn53+FB24pCJC5klX2WU4VOw==", "dev": true, "dependencies": { - "acorn": "^8.8.2", - "acorn-walk": "^8.2.0", + "@vercel/nft": "^0.26.2", + "acorn": "^8.11.3", + "acorn-walk": "^8.3.2", "ansi-styles": "^6.2.1", "arrgv": "^1.0.2", "arrify": "^3.0.0", - "callsites": "^4.0.0", - "cbor": "^8.1.0", - "chalk": "^5.2.0", - "chokidar": "^3.5.3", + "callsites": "^4.1.0", + "cbor": "^9.0.1", + "chalk": "^5.3.0", "chunkd": "^2.0.1", - "ci-info": "^3.8.0", + "ci-info": "^4.0.0", "ci-parallel-vars": "^1.0.1", - "clean-yaml-object": "^0.1.0", - "cli-truncate": "^3.1.0", + "cli-truncate": "^4.0.0", "code-excerpt": "^4.0.0", "common-path-prefix": "^3.0.0", "concordance": "^5.0.4", "currently-unhandled": "^0.4.1", "debug": "^4.3.4", "emittery": "^1.0.1", - "figures": "^5.0.0", - "globby": "^13.1.4", + "figures": "^6.0.1", + "globby": "^14.0.0", "ignore-by-default": "^2.1.0", "indent-string": "^5.0.0", - "is-error": "^2.2.2", "is-plain-object": "^5.0.0", "is-promise": "^4.0.0", "matcher": "^5.0.0", - "mem": "^9.0.2", + "memoize": "^10.0.0", "ms": "^2.1.3", - "p-event": "^5.0.1", - "p-map": "^5.5.0", - "picomatch": "^2.3.1", - "pkg-conf": "^4.0.0", + "p-map": "^7.0.1", + "package-config": "^5.0.0", + "picomatch": "^3.0.1", "plur": "^5.1.0", - "pretty-ms": "^8.0.0", + "pretty-ms": "^9.0.0", "resolve-cwd": "^3.0.0", "stack-utils": "^2.0.6", - "strip-ansi": "^7.0.1", + "strip-ansi": "^7.1.0", "supertap": "^3.0.1", "temp-dir": "^3.0.0", "write-file-atomic": "^5.0.1", @@ -238,7 +341,7 @@ "ava": "entrypoints/cli.mjs" }, "engines": { - "node": ">=14.19 <15 || >=16.15 <17 || >=18" + "node": "^18.18 || ^20.8 || ^21" }, "peerDependencies": { "@ava/typescript": "*" @@ -255,13 +358,13 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "file-uri-to-path": "1.0.0" } }, "node_modules/blueimp-md5": { @@ -304,15 +407,15 @@ } }, "node_modules/cbor": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", - "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", "dev": true, "dependencies": { "nofilter": "^3.1.0" }, "engines": { - "node": ">=12.19" + "node": ">=16" } }, "node_modules/chalk": { @@ -327,31 +430,13 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "node": ">=10" } }, "node_modules/chunkd": { @@ -361,9 +446,9 @@ "dev": true }, "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", + "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", "dev": true, "funding": [ { @@ -381,41 +466,17 @@ "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", "dev": true }, - "node_modules/clean-stack": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz", - "integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "5.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clean-yaml-object": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", - "integrity": "sha512-3yONmlN9CSAkzNwnRCiJQ7Q2xK5mWuEfL3PuTZcAUzhObbXsfsnMptJzXwz93nc5zn9V9TwCVMmV7w4xsm43dw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", + "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, "dependencies": { "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" + "string-width": "^7.0.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -515,12 +576,27 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, "node_modules/common-path-prefix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", "dev": true }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, "node_modules/concordance": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", @@ -540,6 +616,12 @@ "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" } }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "dev": true + }, "node_modules/convert-to-spaces": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", @@ -596,24 +678,21 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, "engines": { "node": ">=8" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, "node_modules/emittery": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.1.tgz", @@ -627,9 +706,9 @@ } }, "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", "dev": true }, "node_modules/escalade": { @@ -666,6 +745,12 @@ "node": ">=4" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -682,9 +767,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -698,30 +783,35 @@ } }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/figures": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz", - "integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/figures/-/figures-6.0.1.tgz", + "integrity": "sha512-0oY/olScYD4IhQ8u//gCPA4F3mlTn2dacYmiDm/mbDQvpmLjV4uH+zhsQ5IyXRyvqkvtUkXkNdGvg5OFJTCsuQ==", "dev": true, "dependencies": { - "escape-string-regexp": "^5.0.0", - "is-unicode-supported": "^1.2.0" + "is-unicode-supported": "^2.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -734,34 +824,122 @@ "node": ">=8" } }, - "node_modules/find-up": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", - "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", + "node_modules/find-up-simple": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", + "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", "dev": true, - "dependencies": { - "locate-path": "^7.1.0", - "path-exists": "^5.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dev": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/gauge/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/gauge/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true + }, + "node_modules/gauge/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/gauge/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">=8" } }, "node_modules/get-caller-file": { @@ -773,6 +951,38 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-east-asian-width": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -785,29 +995,77 @@ "node": ">= 6" } }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/globby": { - "version": "13.2.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz", - "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==", + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.1.tgz", + "integrity": "sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==", "dev": true, "dependencies": { - "dir-glob": "^3.0.1", - "fast-glob": "^3.3.0", + "@sindresorhus/merge-streams": "^2.1.0", + "fast-glob": "^3.3.2", "ignore": "^5.2.4", - "merge2": "^1.4.1", - "slash": "^4.0.0" + "path-type": "^5.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.1.0" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "dev": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" @@ -843,6 +1101,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, "node_modules/irregular-plurals": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", @@ -852,24 +1126,6 @@ "node": ">=8" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-error": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", - "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", - "dev": true - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -928,12 +1184,12 @@ "dev": true }, "node_modules/is-unicode-supported": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz", - "integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", + "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -962,9 +1218,9 @@ } }, "node_modules/jsonc-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", - "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", "dev": true }, "node_modules/load-json-file": { @@ -979,21 +1235,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/locate-path": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", - "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", - "dev": true, - "dependencies": { - "p-locate": "^6.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -1018,16 +1259,28 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "dependencies": { - "p-defer": "^1.0.0" + "semver": "^6.0.0" }, "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" } }, "node_modules/marked": { @@ -1069,20 +1322,19 @@ "node": ">=8" } }, - "node_modules/mem": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/mem/-/mem-9.0.2.tgz", - "integrity": "sha512-F2t4YIv9XQUBHt6AOJ0y7lSmP1+cY7Fm1DRh9GClTGzKST7UWLMx6ly9WZdLH/G/ppM5RL4MlQfRT71ri9t19A==", + "node_modules/memoize": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", + "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", "dev": true, "dependencies": { - "map-age-cleaner": "^0.1.3", - "mimic-fn": "^4.0.0" + "mimic-function": "^5.0.0" }, "engines": { - "node": ">=12.20" + "node": ">=18" }, "funding": { - "url": "https://github.com/sindresorhus/mem?sponsor=1" + "url": "https://github.com/sindresorhus/memoize?sponsor=1" } }, "node_modules/merge2": { @@ -1107,13 +1359,25 @@ "node": ">=8.6" } }, - "node_modules/mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "node_modules/micromatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "engines": { - "node": ">=12" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/mimic-function": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.0.tgz", + "integrity": "sha512-RBfQ+9X9DpXdEoK7Bu+KeEU6vFhumEIiXKWECPzRBmDserEq4uR2b/VCm0LwpMSosoq2k+Zuxj/GzOr0Fn6h/g==", + "dev": true, + "engines": { + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1134,167 +1398,214 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, "engines": { - "node": ">=12.19" + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/node-gyp-build": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", "dev": true, - "engines": { - "node": ">=0.10.0" + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" } }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "node_modules/nofilter": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", + "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", "dev": true, "engines": { - "node": ">=4" + "node": ">=12.19" } }, - "node_modules/p-event": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/p-event/-/p-event-5.0.1.tgz", - "integrity": "sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ==", + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", "dev": true, "dependencies": { - "p-timeout": "^5.0.2" + "abbrev": "1" }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "bin": { + "nopt": "bin/nopt.js" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=6" } }, - "node_modules/p-limit": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", - "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", "dev": true, "dependencies": { - "yocto-queue": "^1.0.0" - }, + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=0.10.0" } }, - "node_modules/p-locate": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", - "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "dependencies": { - "p-limit": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "wrappy": "1" } }, "node_modules/p-map": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-5.5.0.tgz", - "integrity": "sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-7.0.1.tgz", + "integrity": "sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==", "dev": true, - "dependencies": { - "aggregate-error": "^4.0.0" - }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-timeout": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-5.1.0.tgz", - "integrity": "sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==", + "node_modules/package-config": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", + "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", "dev": true, + "dependencies": { + "find-up-simple": "^1.0.0", + "load-json-file": "^7.0.1" + }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/parse-ms": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz", - "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", + "integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==", "dev": true, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/path-exists": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", - "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=0.10.0" } }, "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", + "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", "dev": true, "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/jonschlinkert" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/pkg-conf": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-4.0.0.tgz", - "integrity": "sha512-7dmgi4UY4qk+4mj5Cd8v/GExPo0K+SlY+hulOSdfZ/T6jVH6//y7NtzZo5WrfhDBxuQ0jCa7fLZmNaNh7EWL/w==", + "node_modules/picomatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", + "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", "dev": true, - "dependencies": { - "find-up": "^6.0.0", - "load-json-file": "^7.0.0" - }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/plur": { @@ -1313,15 +1624,15 @@ } }, "node_modules/pretty-ms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", - "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.0.0.tgz", + "integrity": "sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==", "dev": true, "dependencies": { - "parse-ms": "^3.0.0" + "parse-ms": "^4.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1347,16 +1658,18 @@ } ] }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "dependencies": { - "picomatch": "^2.2.1" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" }, "engines": { - "node": ">=8.10.0" + "node": ">= 6" } }, "node_modules/require-directory": { @@ -1399,6 +1712,21 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -1422,6 +1750,26 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -1452,10 +1800,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "dev": true + }, "node_modules/shiki": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", - "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -1477,12 +1831,12 @@ } }, "node_modules/slash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", - "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", "dev": true, "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1531,18 +1885,27 @@ "node": ">=8" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" }, "engines": { - "node": ">=12" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -1578,6 +1941,23 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dev": true, + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/temp-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", @@ -1608,6 +1988,12 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -1626,15 +2012,15 @@ } }, "node_modules/typedoc": { - "version": "0.25.3", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", - "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", + "version": "0.25.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.8.tgz", + "integrity": "sha512-mh8oLW66nwmeB9uTa0Bdcjfis+48bAjSH3uqdzSuSawfduROQLlXw//WSNZLYDdhmMVB7YcYZicq6e8T0d271A==", "dev": true, "dependencies": { "lunr": "^2.3.9", "marked": "^4.3.0", "minimatch": "^9.0.3", - "shiki": "^0.14.1" + "shiki": "^0.14.7" }, "bin": { "typedoc": "bin/typedoc" @@ -1643,13 +2029,13 @@ "node": ">= 16" }, "peerDependencies": { - "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x" } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -1665,6 +2051,24 @@ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true }, + "node_modules/unicorn-magic": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", + "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", @@ -1677,6 +2081,12 @@ "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", "dev": true }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true + }, "node_modules/well-known-symbols": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", @@ -1686,6 +2096,75 @@ "node": ">=6" } }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", @@ -1768,6 +2247,12 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/write-file-atomic": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", @@ -1872,18 +2357,6 @@ "engines": { "node": ">=8" } - }, - "node_modules/yocto-queue": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", - "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } } } } diff --git a/package.json b/package.json index 8d3f174..355f1a3 100644 --- a/package.json +++ b/package.json @@ -1,18 +1,19 @@ { "name": "nkeys.js", - "version": "1.0.6-1", + "version": "1.1.0-1", "description": "A public-key signature system based on Ed25519 for the NATS ecosystem in javascript", "main": "lib/index.js", "types": "lib/index.d.ts", "scripts": { "init": "mkdir -p build", - "clean": "rm -Rf build/ lib/ nkeys.d.ts nkeys.mjs", + "clean": "rm -Rf build/ lib/ nkeys.d.ts nkeys.mjs ./coverage", "fmt": "deno fmt src/ examples/ modules/ test/ node_test/", "cjs": "deno run --allow-all bin/cjs-fix-imports.ts -o build/ src/ modules/cjs/ node_test/", - "generate": "deno run -A --unstable ./bin/tweetnacl-esm.ts", + "generate": "deno run -A ./bin/tweetnacl-esm.ts", "stage": "npm run init && npm run cjs && npm run generate && tsc", "prepare": "npm run stage && npm run generate && deno bundle modules/esm/mod.ts nkeys.mjs && tsc", - "test": "npm run prepare && ava --verbose && deno test -A --unstable test/", + "test": "npm run prepare && ava --verbose && deno test -A test/", + "cover": "npm run clean && npm run prepare && deno test --coverage=coverage -A test/ && deno coverage ./coverage --lcov > ./coverage/out.lcov && genhtml -o ./coverage/html ./coverage/out.lcov && open ./coverage/html/index.html", "doc": "npm run clean && rm -Rf docs && npm run stage && node_modules/.bin/typedoc --out docs/ && touch ./docs/.nojekyll", "bump-qualifier": "npm version prerelease --no-commit-hooks --no-git-tag-version", "bump-release": "npm version patch --no-commit-hooks --no-git-tag-version", @@ -36,10 +37,10 @@ "tweetnacl": "1.0.3" }, "devDependencies": { - "@types/node": "^20.8.x", - "ava": "^5.2.x", - "typedoc": "^0.25.x", - "typescript": "^5.2.x" + "@types/node": "^20.11.x", + "ava": "^6.1.x", + "typedoc": "^0.25.8", + "typescript": "^5.3.3" }, "ava": { "failFast": true, diff --git a/src/curve.ts b/src/curve.ts new file mode 100644 index 0000000..414eece --- /dev/null +++ b/src/curve.ts @@ -0,0 +1,146 @@ +/* + * Copyright 2024 The NATS Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { KeyPair, NKeysError, NKeysErrorCode } from "./nkeys.ts"; +import { getEd25519Helper } from "./helper.ts"; +import { Codec } from "./codec.ts"; +import { Prefix } from "./mod.ts"; +import { base32 } from "./base32.ts"; +import { crc16 } from "./crc16.ts"; + +export const curveKeyLen = 32; +const curveDecodeLen = 35; +export const curveNonceLen = 24; +// "xkv1" in bytes +const XKeyVersionV1 = [120, 107, 118, 49]; + +export class CurveKP implements KeyPair { + seed?: Uint8Array; + + constructor(seed: Uint8Array) { + this.seed = seed; + } + + clear(): void { + if (!this.seed) { + return; + } + this.seed.fill(0); + this.seed = undefined; + } + + getPrivateKey(): Uint8Array { + if (!this.seed) { + throw new NKeysError(NKeysErrorCode.ClearedPair); + } + return Codec.encode(Prefix.Private, this.seed); + } + + getPublicKey(): string { + if (!this.seed) { + throw new NKeysError(NKeysErrorCode.ClearedPair); + } + const pub = getEd25519Helper().scalarBaseMultiply(this.seed); + const buf = Codec.encode(Prefix.Curve, pub); + return new TextDecoder().decode(buf); + } + + getSeed(): Uint8Array { + if (!this.seed) { + throw new NKeysError(NKeysErrorCode.ClearedPair); + } + return Codec.encodeSeed(Prefix.Curve, this.seed); + } + + sign(): Uint8Array { + throw new NKeysError(NKeysErrorCode.InvalidCurveOperation); + } + + verify(): boolean { + throw new NKeysError(NKeysErrorCode.InvalidCurveOperation); + } + + decodePubCurveKey(src: string): Uint8Array { + try { + const raw = base32.decode(new TextEncoder().encode(src)); + if (raw.byteLength !== curveDecodeLen) { + throw new NKeysError(NKeysErrorCode.InvalidCurveKey); + } + if (raw[0] !== Prefix.Curve) { + throw new NKeysError(NKeysErrorCode.InvalidPublicKey); + } + + const checkOffset = raw.byteLength - 2; + const dv = new DataView(raw.buffer); + const checksum = dv.getUint16(checkOffset, true); + const payload = raw.slice(0, checkOffset); + if (!crc16.validate(payload, checksum)) { + throw new NKeysError(NKeysErrorCode.InvalidChecksum); + } + // remove the prefix byte + return payload.slice(1); + } catch (ex) { + throw new NKeysError(NKeysErrorCode.InvalidRecipient, ex); + } + } + + seal(message: Uint8Array, recipient: string, nonce?: Uint8Array): Uint8Array { + if (!this.seed) { + throw new NKeysError(NKeysErrorCode.ClearedPair); + } + if (!nonce) { + nonce = getEd25519Helper().randomBytes(curveNonceLen); + } + let pub = this.decodePubCurveKey(recipient); + + // prefix a header to the nonce + const out = new Uint8Array(XKeyVersionV1.length + curveNonceLen); + out.set(XKeyVersionV1, 0); + out.set(nonce, XKeyVersionV1.length); + + // this is only the encoded payload + const encrypted = getEd25519Helper().seal(message, nonce, pub, this.seed); + // the full message is the header+nonce+encrypted + const fullMessage = new Uint8Array(out.length + encrypted.length); + fullMessage.set(out); + fullMessage.set(encrypted, out.length); + return fullMessage; + } + + open(message: Uint8Array, sender: string): Uint8Array | null { + if (!this.seed) { + throw new NKeysError(NKeysErrorCode.ClearedPair); + } + if (message.length <= curveNonceLen + XKeyVersionV1.length) { + throw new NKeysError(NKeysErrorCode.InvalidEncrypted); + } + for (let i = 0; i < XKeyVersionV1.length; i++) { + if (message[i] !== XKeyVersionV1[i]) { + throw new NKeysError(NKeysErrorCode.InvalidEncrypted); + } + } + + const pub = this.decodePubCurveKey(sender); + + // strip off the header + message = message.slice(XKeyVersionV1.length); + // extract the nonce + const nonce = message.slice(0, curveNonceLen); + // stripe the nonce + message = message.slice(curveNonceLen); + + return getEd25519Helper().open(message, nonce, pub, this.seed); + } +} diff --git a/src/helper.ts b/src/helper.ts index db65820..d2f3b39 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020 The NATS Authors + * Copyright 2020-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -27,6 +27,19 @@ export interface Ed25519Helper { sign(data: Uint8Array, key: Uint8Array): Uint8Array; verify(data: Uint8Array, sig: Uint8Array, pub: Uint8Array): boolean; randomBytes(len: number): Uint8Array; + scalarBaseMultiply(n: Uint8Array): Uint8Array; + seal( + data: Uint8Array, + nonce: Uint8Array, + pub: Uint8Array, + key: Uint8Array, + ): Uint8Array; + open( + data: Uint8Array, + nonce: Uint8Array, + pub: Uint8Array, + key: Uint8Array, + ): Uint8Array; } /** * @ignore diff --git a/src/kp.ts b/src/kp.ts index f63b6d9..0ebdc02 100644 --- a/src/kp.ts +++ b/src/kp.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -82,4 +82,12 @@ export class KP implements KeyPair { this.seed.fill(0); this.seed = undefined; } + + seal(input: Uint8Array, recipient: string, nonce?: Uint8Array): Uint8Array { + throw new NKeysError(NKeysErrorCode.InvalidNKeyOperation); + } + + open(message: Uint8Array, sender: string): Uint8Array | null { + throw new NKeysError(NKeysErrorCode.InvalidNKeyOperation); + } } diff --git a/src/mod.ts b/src/mod.ts index 1755d72..9740dce 100644 --- a/src/mod.ts +++ b/src/mod.ts @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 The NATS Authors + * Copyright 2020-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,10 +16,12 @@ export type { KeyPair } from "./nkeys.ts"; export { createAccount, createCluster, + createCurve, createOperator, createPair, createServer, createUser, + fromCurveSeed, fromPublic, fromSeed, NKeysError, diff --git a/src/nkeys.ts b/src/nkeys.ts index 9661d6f..d00aca9 100644 --- a/src/nkeys.ts +++ b/src/nkeys.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018-2023 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,14 +16,18 @@ import { KP } from "./kp.ts"; import { PublicKey } from "./public.ts"; import { Codec } from "./codec.ts"; import { getEd25519Helper } from "./helper.ts"; +import { curveKeyLen, CurveKP } from "./curve.ts"; /** * @ignore */ export function createPair(prefix: Prefix): KeyPair { - const rawSeed = getEd25519Helper().randomBytes(32); + const len = prefix === Prefix.Curve ? curveKeyLen : 32; + const rawSeed = getEd25519Helper().randomBytes(len); let str = Codec.encodeSeed(prefix, new Uint8Array(rawSeed)); - return new KP(str); + return prefix === Prefix.Curve + ? new CurveKP(new Uint8Array(rawSeed)) + : new KP(str); } /** @@ -64,6 +68,13 @@ export function createServer(): KeyPair { return createPair(Prefix.Server); } +/** + * @ignore + */ +export function createCurve(): KeyPair { + return createPair(Prefix.Curve); +} + /** * Creates a KeyPair from a specified public key * @param {string} src of the public key in string format. @@ -80,6 +91,17 @@ export function fromPublic(src: string): KeyPair { throw new NKeysError(NKeysErrorCode.InvalidPublicKey); } +export function fromCurveSeed(src: Uint8Array): KeyPair { + const sd = Codec.decodeSeed(src); + if (sd.prefix !== Prefix.Curve) { + throw new NKeysError(NKeysErrorCode.InvalidCurveSeed); + } + if (sd.buf.byteLength !== curveKeyLen) { + throw new NKeysError(NKeysErrorCode.InvalidSeedLen); + } + return new CurveKP(sd.buf); +} + /** * Creates a KeyPair from a specified seed. * @param {Uint8Array} src of the seed key as Uint8Array @@ -87,8 +109,11 @@ export function fromPublic(src: string): KeyPair { * @see KeyPair#getSeed */ export function fromSeed(src: Uint8Array): KeyPair { - Codec.decodeSeed(src); - // if we are here it decoded + const sd = Codec.decodeSeed(src); + // if we are here it decoded properly + if (sd.prefix === Prefix.Curve) { + return fromCurveSeed(src); + } return new KP(src); } @@ -137,6 +162,10 @@ export interface KeyPair { * a keypair cannot be used or recovered. */ clear(): void; + + seal(input: Uint8Array, recipient: string, nonce?: Uint8Array): Uint8Array; + + open(message: Uint8Array, sender: string): Uint8Array | null; } /** @@ -165,6 +194,8 @@ export enum Prefix { //PrefixByteUser is the version byte used for encoded NATS Users User = 20 << 3, // Base32-encodes to 'U...' + + Curve = 23 << 3, // Base32-encodes to 'X...' } /** @@ -176,13 +207,14 @@ export class Prefixes { prefix == Prefix.Operator || prefix == Prefix.Cluster || prefix == Prefix.Account || - prefix == Prefix.User; + prefix == Prefix.User || + prefix == Prefix.Curve; } static startsWithValidPrefix(s: string) { let c = s[0]; return c == "S" || c == "P" || c == "O" || c == "N" || c == "C" || - c == "A" || c == "U"; + c == "A" || c == "U" || c == "X"; } static isValidPrefix(prefix: Prefix): boolean { @@ -206,6 +238,8 @@ export class Prefixes { return Prefix.Account; case Prefix.User: return Prefix.User; + case Prefix.Curve: + return Prefix.Curve; default: return Prefix.Unknown; } @@ -221,8 +255,13 @@ export enum NKeysErrorCode { InvalidPublicKey = "nkeys: invalid public key", InvalidSeedLen = "nkeys: invalid seed length", InvalidSeed = "nkeys: invalid seed", + InvalidCurveSeed = "nkeys: invalid curve seed", + InvalidCurveKey = "nkeys: not a valid curve key", + InvalidCurveOperation = "nkeys: curve key is not valid for sign/verify", + InvalidNKeyOperation = "keys: only curve key can seal/open", InvalidEncoding = "nkeys: invalid encoded key", - InvalidSignature = "nkeys: signature verification failed", + InvalidRecipient = "nkeys: not a valid recipient public curve key", + InvalidEncrypted = "nkeys: encrypted input is not valid", CannotSign = "nkeys: cannot sign, no private key available", PublicKeyOnly = "nkeys: no seed or private key available", InvalidChecksum = "nkeys: invalid checksum", diff --git a/src/public.ts b/src/public.ts index d7de271..a3bb1f7 100644 --- a/src/public.ts +++ b/src/public.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -70,4 +70,12 @@ export class PublicKey implements KeyPair { this.publicKey.fill(0); this.publicKey = undefined; } + + seal(input: Uint8Array, recipient: string, nonce?: Uint8Array): Uint8Array { + throw new NKeysError(NKeysErrorCode.InvalidNKeyOperation); + } + + open(message: Uint8Array, sender: string): Uint8Array | null { + throw new NKeysError(NKeysErrorCode.InvalidNKeyOperation); + } } diff --git a/test/basics_test.ts b/test/basics_test.ts index b8fe89f..988defa 100644 --- a/test/basics_test.ts +++ b/test/basics_test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -95,7 +95,7 @@ Deno.test("basics - should fail with non public prefix", () => { Deno.test("basics - should fail getting public key on bad seed", () => { assertThrowsErrorCode(() => { - let kp = new KP(new TextEncoder().encode("SEEDBAD")); + const kp = new KP(new TextEncoder().encode("SEEDBAD")); kp.getPublicKey(); createPair(Prefix.Private); }, NKeysErrorCode.InvalidChecksum); @@ -103,7 +103,7 @@ Deno.test("basics - should fail getting public key on bad seed", () => { Deno.test("basics - should fail getting private key on bad seed", () => { assertThrowsErrorCode(() => { - let kp = new KP(new TextEncoder().encode("SEEDBAD")); + const kp = new KP(new TextEncoder().encode("SEEDBAD")); kp.getPrivateKey(); createPair(Prefix.Private); }, NKeysErrorCode.InvalidChecksum); @@ -111,15 +111,15 @@ Deno.test("basics - should fail getting private key on bad seed", () => { Deno.test("basics - should fail signing on bad seed", () => { assertThrowsErrorCode(() => { - let kp = new KP(new TextEncoder().encode("SEEDBAD")); + const kp = new KP(new TextEncoder().encode("SEEDBAD")); kp.sign(new TextEncoder().encode("HelloWorld")); createPair(Prefix.Private); }, NKeysErrorCode.InvalidChecksum); }); function badKey(): Uint8Array { - let a = createAccount(); - let pk = new TextEncoder().encode(a.getPublicKey()); + const a = createAccount(); + const pk = new TextEncoder().encode(a.getPublicKey()); pk[pk.byteLength - 1] = "0".charCodeAt(0); pk[pk.byteLength - 2] = "0".charCodeAt(0); return pk; @@ -170,14 +170,14 @@ Deno.test("basics - fromPublicKey should reject bad checksum", () => { Deno.test("basics - should reject decoding seed bad checksum", () => { assertThrowsErrorCode(() => { const a = createAccount(); - let pk = a.getPublicKey(); + const pk = a.getPublicKey(); Codec.decodeSeed(new TextEncoder().encode(pk)); }, NKeysErrorCode.InvalidSeed); }); function generateBadSeed(): Uint8Array { const a = createAccount(); - let seed = a.getSeed(); + const seed = a.getSeed(); seed[1] = "S".charCodeAt(0); return seed; } @@ -223,11 +223,11 @@ Deno.test("basics - from public rejects non-public keys", () => { }); Deno.test("basics - test valid prefixes", () => { - let valid = ["S", "P", "O", "N", "C", "A", "U"]; + const valid = ["S", "P", "O", "N", "C", "A", "U", "X"]; valid.forEach((v: string) => { assert(Prefixes.startsWithValidPrefix(v)); }); - const b32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; + const b32 = "ABCDEFGHIJKLMNOPQRSTUVWYZ234567="; b32.split("").forEach((c: string) => { const ok = valid.indexOf(c) !== -1; if (ok) { @@ -238,6 +238,82 @@ Deno.test("basics - test valid prefixes", () => { }); }); +Deno.test("basics - getSeed() fails if cleared", () => { + const a = createAccount(); + a.clear(); + assertThrowsErrorCode(() => { + a.getSeed(); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("basics - getRawSeed() fails if cleared", () => { + const a = createAccount() as KP; + a.clear(); + assertThrowsErrorCode(() => { + a.getRawSeed(); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("basics - clear() clear() is noop", () => { + const a = createAccount(); + a.clear(); + a.clear(); +}); + +Deno.test("basics - verify fails if cleared", () => { + const a = createAccount(); + a.clear(); + assertThrowsErrorCode(() => { + a.verify(new Uint8Array(0), new Uint8Array(0)); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("basics - kp fails seal", () => { + const a = createAccount(); + assertThrowsErrorCode(() => { + a.seal(new Uint8Array(0), ""); + }, NKeysErrorCode.InvalidNKeyOperation); +}); + +Deno.test("basics - kp fails open", () => { + const a = createAccount(); + assertThrowsErrorCode(() => { + a.open(new Uint8Array(0), ""); + }, NKeysErrorCode.InvalidNKeyOperation); +}); + +Deno.test("basics - public verify fails if cleared", () => { + const a = createAccount(); + const pk = fromPublic(a.getPublicKey()); + pk.clear(); + assertThrowsErrorCode(() => { + pk.verify(new Uint8Array(0), new Uint8Array(0)); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("basics - public fails seal", () => { + const a = createAccount(); + const pk = fromPublic(a.getPublicKey()); + assertThrowsErrorCode(() => { + pk.seal(new Uint8Array(0), ""); + }, NKeysErrorCode.InvalidNKeyOperation); +}); + +Deno.test("basics - public clear() clear() is noop", () => { + const a = createAccount(); + const pk = fromPublic(a.getPublicKey()); + pk.clear(); + pk.clear(); +}); + +Deno.test("basics - public fails open", () => { + const a = createAccount(); + const pk = fromPublic(a.getPublicKey()); + assertThrowsErrorCode(() => { + pk.open(new Uint8Array(0), ""); + }, NKeysErrorCode.InvalidNKeyOperation); +}); + function testClear(kp: KeyPair) { kp.clear(); diff --git a/test/codec_test.ts b/test/codec_test.ts index f344553..97ececd 100644 --- a/test/codec_test.ts +++ b/test/codec_test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -20,7 +20,7 @@ import { NKeysErrorCode, Prefix } from "../src/nkeys.ts"; Deno.test("codec - should fail to encode non Uint8Array", () => { assertThrowsErrorCode(() => { - //@ts-ignore + //@ts-ignore: negative test Codec.encode(Prefix.Private, 10); }, NKeysErrorCode.SerializationError); }); @@ -67,7 +67,7 @@ Deno.test("codec - should encode and decode seed", () => { assertEquals(enc[0], "S".charCodeAt(0)); assertEquals(enc[1], "A".charCodeAt(0)); - let seed = Codec.decodeSeed(enc); + const seed = Codec.decodeSeed(enc); assertEquals(seed.prefix, Prefix.Account); assertEquals(seed.buf, rand); }); @@ -86,38 +86,38 @@ Deno.test("codec - should fail to short string", () => { Deno.test("codec - decode with invalid role should fail", () => { const rand = globalThis.crypto.getRandomValues(new Uint8Array(32)); - //@ts-ignore + //@ts-ignore: negative test const badSeed = Codec._encode(false, "R", rand); assertThrowsErrorCode(() => { - //@ts-ignore + //@ts-ignore: negative test Codec.decode("Z", badSeed); }, NKeysErrorCode.InvalidPrefixByte); }); Deno.test("codec - encode seed requires buffer", () => { - //@ts-ignore + //@ts-ignore: negative test assertThrowsErrorCode(() => { - //@ts-ignore + //@ts-ignore: negative test Codec.encodeSeed(false, Prefix.Account, "foo"); }, NKeysErrorCode.ApiError); }); Deno.test("codec - decodeSeed with invalid role should fail", () => { const rand = globalThis.crypto.getRandomValues(new Uint8Array(32)); - const badRole = 23 << 3; // X - //@ts-ignore + const badRole = 24 << 3; // Y + //@ts-ignore: negative test const badSeed = Codec._encode(true, badRole, rand); assertThrowsErrorCode(() => { - //@ts-ignore + //@ts-ignore: negative test Codec.decodeSeed(badSeed); }, NKeysErrorCode.InvalidPrefixByte); }); Deno.test("codec - decode unexpected prefix should fail", () => { const rand = globalThis.crypto.getRandomValues(new Uint8Array(32)); - let seed = Codec._encode(false, Prefix.Account, rand); + const seed = Codec._encode(false, Prefix.Account, rand); assertThrowsErrorCode(() => { - //@ts-ignore + //@ts-ignore: negative test Codec.decode(Prefix.User, seed); }, NKeysErrorCode.InvalidPrefixByte); }); diff --git a/test/curve_test.ts b/test/curve_test.ts new file mode 100644 index 0000000..4093ed8 --- /dev/null +++ b/test/curve_test.ts @@ -0,0 +1,337 @@ +/* + * Copyright 2024 The NATS Authors + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { + createCurve, + fromCurveSeed, + fromSeed, + NKeysErrorCode, +} from "../modules/esm/mod.ts"; +import { + assert, + assertEquals, +} from "https://deno.land/std@0.200.0/assert/mod.ts"; +import { assertThrowsErrorCode } from "./util.ts"; +import { CurveKP } from "../src/curve.ts"; +import { createAccount } from "../src/nkeys.ts"; +import { base32 } from "../src/base32.ts"; + +Deno.test("curve - transitive parse", () => { + const seed = "SXABQYG6TLQOAZSOGFIAPFJ6B5ZPUXKK5USV4UGXTULPGLSNTSZWJPTLEI"; + const pub = "XBJKZV6QJMJAN3H3KFL2NFVJEQ4WW22423DKRNYF4OIB6LWHUC4COBP6"; + const kp = fromSeed(new TextEncoder().encode(seed)); + + const seed2 = new TextDecoder().decode(kp.getSeed()); + assertEquals(seed, seed2); + const pub2 = kp.getPublicKey(); + assertEquals(pub, pub2); +}); + +Deno.test("curve - new", () => { + const kp = createCurve(); + const seed = kp.getSeed(); + const pub = kp.getPublicKey(); + + const kp2 = fromSeed(seed); + const pub2 = kp2.getPublicKey(); + assertEquals(pub, pub2); +}); + +Deno.test("curve - encrypt", () => { + // this is actual data generated by the nkeys go library + const expected = [ + 120, + 107, + 118, + 49, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 103, + 188, + 195, + 73, + 0, + 3, + 119, + 91, + 181, + 167, + 162, + 167, + 105, + 51, + 102, + 84, + 94, + 152, + 189, + 229, + 149, + 222, + 47, + 17, + 149, + 188, + 170, + ]; + const secret = "SXAESVBNK3UN2O24Z53ZJLFMX5OYHLAAVULRILWXRO775SDYFKI7FM3J7Y"; + const recipient = + "SXAHMGVNIYUF4CA5G475EN64YWNG32HSIF4MZCPZHV7PAFYTWBE5J5USFE"; + + // parse the imported secret and public + const kp = fromSeed(new TextEncoder().encode(secret)); + const kp2 = fromSeed(new TextEncoder().encode(recipient)); + const pub2 = kp2.getPublicKey(); + + // nonce is 24 empty bytes for ease of inspection + const nonce = new Uint8Array(24); + const data = new TextEncoder().encode("hello world"); + + const enc = kp.seal(data, pub2, nonce); + assertEquals(enc, new Uint8Array(expected)); +}); + +Deno.test("curve - decrypt", () => { + // this is actual data generated by the nkeys go library + const message = [ + 120, + 107, + 118, + 49, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 103, + 188, + 195, + 73, + 0, + 3, + 119, + 91, + 181, + 167, + 162, + 167, + 105, + 51, + 102, + 84, + 94, + 152, + 189, + 229, + 149, + 222, + 47, + 17, + 149, + 188, + 170, + ]; + const sender = "SXAESVBNK3UN2O24Z53ZJLFMX5OYHLAAVULRILWXRO775SDYFKI7FM3J7Y"; + const secret = "SXAHMGVNIYUF4CA5G475EN64YWNG32HSIF4MZCPZHV7PAFYTWBE5J5USFE"; + + // parse the imported secret and public + const kp = fromSeed(new TextEncoder().encode(secret)); + const kp2 = fromSeed(new TextEncoder().encode(sender)); + const senderPK = kp2.getPublicKey(); + + const enc = kp.open(new Uint8Array(message), senderPK) ?? new Uint8Array(); + assertEquals(new TextDecoder().decode(enc), "hello world"); +}); + +Deno.test("curve - getSeed() fails if cleared", () => { + const a = createCurve(); + a.clear(); + assertThrowsErrorCode(() => { + a.getSeed(); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("curve - clear() clear() is noop", () => { + const a = createCurve(); + a.clear(); + a.clear(); +}); + +Deno.test("curve - getPublicKey() fails if cleared", () => { + const a = createCurve(); + a.clear(); + assertThrowsErrorCode(() => { + a.getPublicKey(); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("curve - seal() fails if cleared", () => { + const a = createCurve(); + a.clear(); + assertThrowsErrorCode(() => { + a.seal(new Uint8Array(0), ""); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("curve - seal() adds random nonce", () => { + const a = createCurve(); + const b = createCurve(); + const pub = b.getPublicKey(); + const msg = a.seal(new Uint8Array(0), pub); + const nonce = msg.slice(4, 28); + let sum = 0; + for (let i = 0; i < nonce.length; i++) { + sum += nonce[i]; + } + assert(sum > 0); +}); + +Deno.test("curve - open() fails if cleared", () => { + const a = createCurve(); + a.clear(); + assertThrowsErrorCode(() => { + a.open(new Uint8Array(0), ""); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("curve - open() bad message", () => { + const a = createCurve(); + assertThrowsErrorCode(() => { + a.open(new Uint8Array(28), ""); + }, NKeysErrorCode.InvalidEncrypted); +}); + +Deno.test("curve - open() bad version", () => { + const a = createCurve(); + assertThrowsErrorCode(() => { + const m = new Uint8Array(29); + m.set([120, 107, 118, 50]); + a.open(m, ""); + }, NKeysErrorCode.InvalidEncrypted); +}); + +Deno.test("curve - sign() is invalid operation", () => { + const a = createCurve(); + assertThrowsErrorCode(() => { + a.sign(new Uint8Array(0)); + }, NKeysErrorCode.InvalidCurveOperation); +}); + +Deno.test("curve - verify() is invalid operation", () => { + const a = createCurve(); + assertThrowsErrorCode(() => { + a.verify(new Uint8Array(0), new Uint8Array(0)); + }, NKeysErrorCode.InvalidCurveOperation); +}); + +Deno.test("curve - decode bad recipient", () => { + const a = createCurve() as CurveKP; + assertThrowsErrorCode(() => { + a.decodePubCurveKey(createAccount().getPublicKey()); + }, NKeysErrorCode.InvalidRecipient); +}); + +Deno.test("curve - decode bad recipient", () => { + const a = createCurve() as CurveKP; + assertThrowsErrorCode(() => { + const key = new TextEncoder().encode("hello world"); + a.decodePubCurveKey(new TextDecoder().decode(base32.encode(key))); + }, NKeysErrorCode.InvalidRecipient); +}); + +Deno.test("curve - decode bad recipient - crc", () => { + const bad = "XBJKZV6QJMJAN3H3KFL2LFVJEQ4WW22423DKRNYF4OIB6LWHUC4COBP6"; + const a = createCurve() as CurveKP; + assertThrowsErrorCode(() => { + a.decodePubCurveKey(bad); + }, NKeysErrorCode.InvalidRecipient); +}); + +Deno.test("curve - private key", () => { + const expected = "PBEVILKW5DOTWXGPO6KKZLF7LWB2YAFNC4KC5V4LX77MQ6BKSHZLGV6X"; + const ck = fromSeed( + new TextEncoder().encode( + "SXAESVBNK3UN2O24Z53ZJLFMX5OYHLAAVULRILWXRO775SDYFKI7FM3J7Y", + ), + ); + const priv = new TextDecoder().decode(ck.getPrivateKey()); + assertEquals(priv, expected); +}); + +Deno.test("curve - private key cleared", () => { + const ck = createCurve(); + ck.clear(); + assertThrowsErrorCode(() => { + ck.getPrivateKey(); + }, NKeysErrorCode.ClearedPair); +}); + +Deno.test("curve - fromCurveSeed bad key", () => { + const a = createAccount(); + assertThrowsErrorCode(() => { + fromCurveSeed(a.getSeed()); + }, NKeysErrorCode.InvalidCurveSeed); +}); + +Deno.test("curve - basics", () => { + const sender = createCurve(); + const recipient = createCurve(); + + const data = new TextEncoder().encode("hello world"); + const edata = sender.seal(data, recipient.getPublicKey()); + const ddata = recipient.open(edata, sender.getPublicKey()); + assertEquals(data, ddata); +}); diff --git a/test/integration_test.ts b/test/integration_test.ts index 3f49b28..df9d8ab 100644 --- a/test/integration_test.ts +++ b/test/integration_test.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -23,7 +23,7 @@ import { Codec } from "../src/codec.ts"; import { Prefix } from "../src/nkeys.ts"; // this was generated using nkey api in go -let data = { +const data = { "seed": "SAAFYOZ5U4UBAJMHPITLSKDWAFBJNWH53K7LPZDQKOC5TXAGBIP4DY4WCA", "public_key": "AAASUT7FDZDS6UCTBE7JQS2G6KUZBJC5YW7VFVK45JLUK3UDVA6NXJWD", "private_key": @@ -36,8 +36,8 @@ let data = { Deno.test("integration - verify", () => { const te = new TextEncoder(); const pk = fromPublic(data.public_key); - let nonce = te.encode(data.nonce); - let sig = decode(data.sig); + const nonce = te.encode(data.nonce); + const sig = decode(data.sig); assert(pk.verify(nonce, sig)); const seed = fromSeed(te.encode(data.seed)); @@ -48,7 +48,7 @@ Deno.test("integration - verify", () => { }); Deno.test("integration - encoded seed returns stable values albertor", () => { - let data = { + const data = { "seed": "SUAGC3DCMVZHI33SMFWGEZLSORXXEYLMMJSXE5DPOJQWYYTFOJ2G64VAPY", "public_key": "UAHJLSMYZDJCBHQ2SARL37IEALR3TI7VVPZ2MJ7F4SZKNOG7HJJIYW5T", "private_key": diff --git a/test/util.ts b/test/util.ts index 772b12e..00e9ddc 100644 --- a/test/util.ts +++ b/test/util.ts @@ -1,5 +1,5 @@ /* - * Copyright 2018-2020 The NATS Authors + * Copyright 2018-2024 The NATS Authors * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -15,7 +15,7 @@ import { assert, fail } from "https://deno.land/std@0.75.0/testing/asserts.ts"; -export function assertThrowsErrorCode(fn: () => any, ...codes: string[]) { +export function assertThrowsErrorCode(fn: () => unknown, ...codes: string[]) { try { fn(); fail("failed to throw error"); @@ -31,8 +31,8 @@ export function assertErrorCode(err: Error, ...codes: string[]) { const ok = codes.find((c) => { return code === c; }); - if (!ok) { - debugger; - } + // if (!ok) { + // debugger; + // } assert(ok); }