From baf007718cc6e9e7e908ba4ec9a1624be3990b8b Mon Sep 17 00:00:00 2001 From: Paul Miller Date: Fri, 10 Jan 2025 22:54:31 +0000 Subject: [PATCH] Run tests in bun, deno --- .github/workflows/coverage.yml | 17 -------- .github/workflows/nodejs.yml | 24 ----------- .github/workflows/publish-jsr.yml | 15 ------- .github/workflows/publish-npm.yml | 23 ---------- .github/workflows/release.yml | 57 +++++++++++++++++++++++++ .github/workflows/test-js.yml | 64 ++++++++++++++++++++++++++++ .github/workflows/upload-release.yml | 28 ------------ package.json | 2 +- test/avcp.test.js | 8 ++-- test/index.js | 4 +- test/ml-dsa.test.js | 20 --------- test/ml-kem.test.js | 36 ---------------- test/slh-kem.test.js | 41 ------------------ test/util.js | 16 ++++--- 14 files changed, 137 insertions(+), 218 deletions(-) delete mode 100644 .github/workflows/coverage.yml delete mode 100644 .github/workflows/nodejs.yml delete mode 100644 .github/workflows/publish-jsr.yml delete mode 100644 .github/workflows/publish-npm.yml create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/test-js.yml delete mode 100644 .github/workflows/upload-release.yml delete mode 100644 test/ml-dsa.test.js delete mode 100644 test/ml-kem.test.js delete mode 100644 test/slh-kem.test.js diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml deleted file mode 100644 index 07377a5..0000000 --- a/.github/workflows/coverage.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Measure test coverage -on: - - push - - pull_request -jobs: - coverage: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 - with: - node-version: 22 - registry-url: 'https://registry.npmjs.org' - cache: npm - - run: npm install - - run: npm run build --if-present - - run: npm run test:coverage diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml deleted file mode 100644 index 0adc854..0000000 --- a/.github/workflows/nodejs.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: Run node.js tests -on: - - push - - pull_request -jobs: - test: - name: v${{ matrix.node }} @ ubuntu-latest - runs-on: ubuntu-latest - strategy: - matrix: - node: - - 18 - - 20 - - 22 - steps: - - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 - with: - node-version: ${{ matrix.node }} - - run: npm install - - run: npm run build --if-present - - run: npm test - - run: npm run lint --if-present diff --git a/.github/workflows/publish-jsr.yml b/.github/workflows/publish-jsr.yml deleted file mode 100644 index 3245758..0000000 --- a/.github/workflows/publish-jsr.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: Publish package to jsr -on: - release: - types: [created] - workflow_dispatch: -jobs: - publish: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - - run: npm install -g jsr - - run: jsr publish diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml deleted file mode 100644 index cd57db8..0000000 --- a/.github/workflows/publish-npm.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Publish package to npm -on: - release: - types: [created] -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: read - id-token: write - steps: - - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 - with: - node-version: 20 - registry-url: 'https://registry.npmjs.org' - cache: npm - - run: npm install -g npm - - run: npm ci - - run: npm run build - - run: npm publish --provenance --access public - env: - NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..2bf740a --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,57 @@ +name: Publish release +on: + release: + types: [created] + workflow_dispatch: +jobs: + publish-jsr: + name: Publish to JSR.io + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - run: npm install -g jsr + - run: jsr publish + publish-npm: + name: Publish to NPM + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: 22 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm ci + - run: npm run build + - run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} + standalone: + name: Upload files to GitHub Releases + runs-on: ubuntu-latest + permissions: + contents: write + id-token: write + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: 22 + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm ci + - run: npm run build + - run: | + cd build + npm ci + npm run build:release + cd .. + - run: gh release upload ${{ github.event.release.tag_name }} build/`npx jsbt outfile` + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/test-js.yml b/.github/workflows/test-js.yml new file mode 100644 index 0000000..2160ced --- /dev/null +++ b/.github/workflows/test-js.yml @@ -0,0 +1,64 @@ +name: Run JS tests +on: + - push + - pull_request +jobs: + bun: + name: Bun + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1 + - run: bun install + - run: bun run build + - run: bun test/index.js + deno: + name: Deno + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: denoland/setup-deno@909cc5acb0fdd60627fb858598759246509fa755 # v2.0.2 + - run: deno install + - run: deno task build + - run: deno --allow-env --allow-read --allow-write test/index.js + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install + - run: npm run build --if-present + - run: npm run lint --if-present + node: + name: Node v${{ matrix.node }} + runs-on: ubuntu-latest + strategy: + matrix: + node: [14, 16, 18, 20, 22] + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - name: Use Node.js ${{ matrix.node }} + uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + node-version: ${{ matrix.node }} + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install + - run: npm run build --if-present + - run: npm test + coverage: + name: Measure coverage on Node + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 + - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 + with: + registry-url: 'https://registry.npmjs.org' + cache: npm + - run: npm install + - run: npm run build --if-present + - run: npm run test:coverage diff --git a/.github/workflows/upload-release.yml b/.github/workflows/upload-release.yml deleted file mode 100644 index b8c2ca9..0000000 --- a/.github/workflows/upload-release.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Upload standalone file to GitHub Releases -on: - release: - types: [created] -jobs: - build: - runs-on: ubuntu-latest - permissions: - contents: write - id-token: write - steps: - - uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4 - - uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4 - with: - node-version: 20 - registry-url: 'https://registry.npmjs.org' - cache: npm - - run: npm install -g npm - - run: npm ci - - run: npm run build - - run: | - cd build - npm ci - npm run build:release - cd .. - - run: gh release upload ${{ github.event.release.tag_name }} build/`npx jsbt outfile` - env: - GH_TOKEN: ${{ github.token }} diff --git a/package.json b/package.json index 8386fd6..d55202a 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "bench": "node benchmark/ml-kem.js noble; node benchmark/ml-dsa.js noble; node benchmark/slh-dsa.js noble", "bench:all": "node benchmark/{ml-kem,ml-dsa,slh-dsa}.js", "bench:install": "cd benchmark && npm install && cd ../../", - "build": "npm run build:clean; tsc && tsc -p tsconfig.esm.json", + "build": "tsc && tsc -p tsconfig.esm.json", "build:release": "cd build; npm i; npm run build", "build:clean": "rm {.,esm}/*.{js,d.ts,d.ts.map,js.map} 2> /dev/null", "lint": "prettier --check 'src/**/*.{js,ts}' 'test/**/*.{js,ts,mjs}'", diff --git a/test/avcp.test.js b/test/avcp.test.js index 70e39c8..5c84db6 100644 --- a/test/avcp.test.js +++ b/test/avcp.test.js @@ -2,8 +2,8 @@ import { deepStrictEqual, throws } from 'node:assert'; import { pathToFileURL } from 'node:url'; import { describe, should } from 'micro-should'; import { concatBytes, hexToBytes } from '@noble/hashes/utils'; -import { ml_dsa44, ml_dsa65, ml_dsa87 } from '../ml-dsa.js'; -import { ml_kem512, ml_kem768, ml_kem1024 } from '../ml-kem.js'; +import { ml_dsa44, ml_dsa65, ml_dsa87 } from '../esm/ml-dsa.js'; +import { ml_kem512, ml_kem768, ml_kem1024 } from '../esm/ml-kem.js'; import { slh_dsa_shake_128f, slh_dsa_shake_128s, @@ -17,7 +17,7 @@ import { slh_dsa_sha2_192s, slh_dsa_sha2_256f, slh_dsa_sha2_256s, -} from '../slh-dsa.js'; +} from '../esm/slh-dsa.js'; import { jsonGZ } from './util.js'; // TODO: use in other libraries? seems useful @@ -188,5 +188,5 @@ if (import.meta.url === pathToFileURL(process.argv[1]).href) { /* NOTE: we pass tests from NIST test vectors, however: - HashML-DSA/HashSLH-DSA not implemented (there is no tests for them) -- +- */ diff --git a/test/index.js b/test/index.js index ee33006..0ca076c 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,6 @@ import { should } from 'micro-should'; -import './ml-kem.test.js'; -import './ml-dsa.test.js'; +// import './ml-kem.test.js'; +// import './ml-dsa.test.js'; import './avcp.test.js'; // Test vectors from 'AVCP' // ESM is broken. diff --git a/test/ml-dsa.test.js b/test/ml-dsa.test.js deleted file mode 100644 index de46171..0000000 --- a/test/ml-dsa.test.js +++ /dev/null @@ -1,20 +0,0 @@ -import { deepStrictEqual } from 'node:assert'; -import { describe, should } from 'micro-should'; -import { hexToBytes } from '@noble/hashes/utils'; - -import { ml_dsa44, ml_dsa65, ml_dsa87 } from '../ml-dsa.js'; - -describe('ML-DSA Dilithium', () => { - should('Example', () => { - const aliceKeys = ml_dsa65.keygen(); - const msg = new Uint8Array(1); - const sig = ml_dsa65.sign(aliceKeys.secretKey, msg); - const isValid = ml_dsa65.verify(aliceKeys.publicKey, msg, sig); - }); -}); - -// ESM is broken. -import url from 'node:url'; -if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { - should.run(); -} diff --git a/test/ml-kem.test.js b/test/ml-kem.test.js deleted file mode 100644 index 3df5c11..0000000 --- a/test/ml-kem.test.js +++ /dev/null @@ -1,36 +0,0 @@ -import { deepStrictEqual, notDeepStrictEqual, throws } from 'node:assert'; -import { pathToFileURL } from 'node:url'; -import { describe, should } from 'micro-should'; -import { ml_kem512, ml_kem768, ml_kem1024 } from '../ml-kem.js'; -import { __dirname } from './util.js'; - -describe('ML-KEM Kyber', () => { - should('Example', () => { - // Alice generates keys - const aliceKeys = ml_kem1024.keygen(); // [Alice] generates key pair (secret and public key) - const alicePub = aliceKeys.publicKey; // [Alice] sends public key to Bob (somehow) - // aliceKeys.secretKey never leaves [Alice] system and unknown to other parties - - // Bob creates cipherText for Alice - // [Bob] generates shared secret for Alice publicKey - const { cipherText, sharedSecret: bobShared } = ml_kem1024.encapsulate(alicePub); - // bobShared never leaves [Bob] system and unknown to other parties - - // Alice gets cipherText from Bob - // [Alice] decrypts sharedSecret from Bob - const aliceShared = ml_kem1024.decapsulate(cipherText, aliceKeys.secretKey); - - // Now, both Alice and Both have same sharedSecret key without exchanging in plainText - deepStrictEqual(aliceShared, bobShared); - - // Warning: Can be MITM-ed - const carolKeys = ml_kem1024.keygen(); - const carolShared = ml_kem1024.decapsulate(cipherText, carolKeys.secretKey); // No error! - notDeepStrictEqual(aliceShared, carolShared); // Different key! - }); -}); - -// ESM is broken. -if (import.meta.url === pathToFileURL(process.argv[1]).href) { - should.run(); -} diff --git a/test/slh-kem.test.js b/test/slh-kem.test.js deleted file mode 100644 index 0f15501..0000000 --- a/test/slh-kem.test.js +++ /dev/null @@ -1,41 +0,0 @@ -import { deepStrictEqual } from 'node:assert'; -import { describe, should } from 'micro-should'; -import { aes256_ctr_drbg } from './_drbg.js'; -import { readKAT } from './util.js'; -import { concatBytes, hexToBytes } from '@noble/hashes/utils'; -import * as sphincs_sha2 from '../slh-dsa.js'; -import * as sphincs_shake from '../slh-dsa.js'; - -import { - slh_dsa_shake_128f, - slh_dsa_shake_128s, - slh_dsa_shake_192f, - slh_dsa_shake_192s, - slh_dsa_shake_256f, - slh_dsa_shake_256s, -} from '../slh-dsa.js'; - -import { - slh_dsa_sha2_128f, - slh_dsa_sha2_128s, - slh_dsa_sha2_192f, - slh_dsa_sha2_192s, - slh_dsa_sha2_256f, - slh_dsa_sha2_256s, -} from '../slh-dsa.js'; - -describe('SLH-DSA SPHINCS', () => { - should('Example', () => { - const sph = slh_dsa_sha2_128f; - const aliceKeys = sph.keygen(); - const msg = new Uint8Array(1); - const sig = sph.sign(aliceKeys.secretKey, msg); - const isValid = sph.verify(aliceKeys.publicKey, msg, sig); - }); -}); - -// ESM is broken. -import url from 'node:url'; -if (import.meta.url === url.pathToFileURL(process.argv[1]).href) { - should.run(); -} diff --git a/test/util.js b/test/util.js index 43526c4..6ff6cfd 100644 --- a/test/util.js +++ b/test/util.js @@ -4,13 +4,17 @@ import { fileURLToPath } from 'node:url'; import { gunzipSync } from 'node:zlib'; export const __dirname = dirname(fileURLToPath(import.meta.url)); -const readGZ = (path) => { +function readGZ(path) { let data = readFileSync(`${__dirname}/${path}`); if (path.endsWith('.gz')) data = gunzipSync(data); - return Buffer.from(data).toString('utf8'); -}; + return new TextDecoder().decode(data); +} -export const readKAT = (name, firstField) => { +export function jsonGZ(path) { + return JSON.parse(readGZ(path)); +} + +export function readKAT(name, firstField) { const data = readGZ(`vectors/KAT/${name}`); let cases; if (!firstField) cases = data.split(/\n\n/gm); @@ -34,6 +38,4 @@ export const readKAT = (name, firstField) => { res.push(out); } return res; -}; - -export const jsonGZ = (path) => JSON.parse(readGZ(path)); +}