Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jest to vitest #29

Merged
merged 1 commit into from
Mar 10, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node: [20, 18]
node: [22, 20]
steps:
- name: Checking out
uses: actions/checkout@v4
Expand Down
6 changes: 3 additions & 3 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import eslintJS from '@eslint/js'
import eslintTS from 'typescript-eslint'
import pluginPrettier from 'eslint-plugin-prettier/recommended'
import pluginSecurity from 'eslint-plugin-security'
import pluginJest from 'eslint-plugin-jest'
import pluginVitest from 'eslint-plugin-vitest'

export default eslintTS.config(
eslintJS.configs.recommended,
...eslintTS.configs.strictTypeChecked,
pluginJest.configs['flat/recommended'],
pluginVitest.configs.recommended,
pluginSecurity.configs.recommended,
{
ignores: [
'jest.config.mjs',
'vitest.config.ts',
'eslint.config.mjs',
'coverage/*',
'src/sjcl/index.js',
Expand Down
12 changes: 0 additions & 12 deletions jest.config.json

This file was deleted.

5,868 changes: 2,155 additions & 3,713 deletions package-lock.json

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
"homepage": "https://github.com/cloudflare/blindrsa-ts#readme",
"repository": "github:cloudflare/blindrsa-ts",
"engines": {
"node": ">=18"
"node": ">=20"
},
"scripts": {
"build": "tsc -b && cp src/sjcl/index.d.ts lib/src/sjcl/index.d.ts",
"test": "tsc -b test && node --experimental-vm-modules node_modules/jest/bin/jest.js --ci",
"test": "tsc -b test && vitest --run",
"lint": "eslint .",
"format": "prettier './(src|test|examples)/**/!(*.d).ts' --write",
"bench": "tsc -b bench && node ./lib/bench/index.js",
Expand All @@ -42,17 +42,17 @@
"devDependencies": {
"@eslint/js": "9.11.1",
"@types/benchmark": "2.1.5",
"@types/jest": "29.5.13",
"@vitest/coverage-v8": "3.0.7",
"benchmark": "2.1.4",
"eslint": "9.11.1",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-jest": "28.8.3",
"eslint-plugin-prettier": "5.2.1",
"eslint-plugin-security": "3.0.1",
"jest": "29.7.0",
"eslint-plugin-vitest": "0.5.4",
"prettier": "3.3.3",
"rimraf": "6.0.1",
"typescript": "5.6.2",
"typescript-eslint": "8.8.0"
"typescript-eslint": "8.8.0",
"vitest": "3.0.7"
}
}
44 changes: 20 additions & 24 deletions test/blindrsa.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2023 Cloudflare, Inc.
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

import { jest } from '@jest/globals';
import { beforeEach, describe, expect, test, vi } from 'vitest';

import sjcl from '../src/sjcl/index.js';
import { i2osp } from '../src/util.js';
Expand Down Expand Up @@ -77,7 +77,7 @@ test('Parameters', () => {
}
});

describe.each(vectors)('Errors-vec$#', (v: Vector) => {
describe.each(vectors)('Errors-vec%#', (v: Vector) => {
test('non-extractable-keys', async () => {
const { privateKey, publicKey } = await keysFromVector(v, false);
const msg = crypto.getRandomValues(new Uint8Array(10));
Expand Down Expand Up @@ -125,7 +125,7 @@ describe.each(vectors)('TestVectors', (v: Vector) => {
const r = rInv.inverseMod(n);
const rBytes = i2osp(r, kLen);

jest.spyOn(crypto, 'getRandomValues')
vi.spyOn(crypto, 'getRandomValues')
.mockReturnValueOnce(hexToUint8(v.msg_prefix)) // mock for msg_prefix
.mockReturnValueOnce(hexToUint8(v.salt)) // mock for random salt
.mockReturnValueOnce(rBytes); // mock for random blind
Expand All @@ -134,32 +134,28 @@ describe.each(vectors)('TestVectors', (v: Vector) => {
const params = [undefined, { supportsRSARAW: true }];

describe.each(params)(`_${v.name}`, (params) => {
test(
`supportsRSARAW/${params ? params.supportsRSARAW : false}`,
async () => {
const blindRSA = getSuiteByName(BlindRSA, v.name, params);
expect(blindRSA.toString()).toBe(v.name);
test(`supportsRSARAW/${params ? params.supportsRSARAW : false}`, async () => {
const blindRSA = getSuiteByName(BlindRSA, v.name, params);
expect(blindRSA.toString()).toBe(v.name);

const msg = hexToUint8(v.msg);
const inputMsg = blindRSA.prepare(msg);
expect(uint8ToHex(inputMsg)).toBe(v.input_msg);
const msg = hexToUint8(v.msg);
const inputMsg = blindRSA.prepare(msg);
expect(uint8ToHex(inputMsg)).toBe(v.input_msg);

const { publicKey, privateKey } = await keysFromVector(v, true);
const { publicKey, privateKey } = await keysFromVector(v, true);

const { blindedMsg, inv } = await blindRSA.blind(publicKey, inputMsg);
expect(uint8ToHex(blindedMsg)).toBe(v.blinded_msg);
expect(uint8ToHex(inv)).toBe(v.inv.slice(2));
const { blindedMsg, inv } = await blindRSA.blind(publicKey, inputMsg);
expect(uint8ToHex(blindedMsg)).toBe(v.blinded_msg);
expect(uint8ToHex(inv)).toBe(v.inv.slice(2));

const blindedSig = await blindRSA.blindSign(privateKey, blindedMsg);
expect(uint8ToHex(blindedSig)).toBe(v.blind_sig);
const blindedSig = await blindRSA.blindSign(privateKey, blindedMsg);
expect(uint8ToHex(blindedSig)).toBe(v.blind_sig);

const signature = await blindRSA.finalize(publicKey, inputMsg, blindedSig, inv);
expect(uint8ToHex(signature)).toBe(v.sig);
const signature = await blindRSA.finalize(publicKey, inputMsg, blindedSig, inv);
expect(uint8ToHex(signature)).toBe(v.sig);

const isValid = await blindRSA.verify(publicKey, signature, inputMsg);
expect(isValid).toBe(true);
},
20 * 1000,
);
const isValid = await blindRSA.verify(publicKey, signature, inputMsg);
expect(isValid).toBe(true);
}, 300_000);
});
});
6 changes: 3 additions & 3 deletions test/misc.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2023 Cloudflare, Inc.
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

import { jest } from '@jest/globals';
import { expect, test, vi } from 'vitest';

import { emsa_pss_encode, is_coprime, random_integer_uniform } from '../src/util.js';
import sjcl from '../src/sjcl/index.js';
Expand All @@ -17,7 +17,7 @@ test('emsa_pss_encode', async () => {
const salt = hexToUint8(vector.salt);
const sLen = salt.length;

jest.spyOn(crypto, 'getRandomValues').mockReturnValueOnce(salt);
vi.spyOn(crypto, 'getRandomValues').mockReturnValueOnce(salt);

const encoded = await emsa_pss_encode(msg, 1023, { hash, sLen });
expect(encoded).toStrictEqual(hexToUint8(vector.expected));
Expand All @@ -36,6 +36,6 @@ test('random_integer_uniform', () => {
const mLen = 2;
const zeros = new Uint8Array(mLen);

jest.spyOn(crypto, 'getRandomValues').mockReturnValue(zeros);
vi.spyOn(crypto, 'getRandomValues').mockReturnValue(zeros);
expect(() => random_integer_uniform(m, mLen)).toThrow(Error);
});
78 changes: 36 additions & 42 deletions test/partially_blindrsa.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

import sjcl from '../src/sjcl/index.js';
import { jest } from '@jest/globals';
import { beforeEach, describe, expect, test, vi } from 'vitest';

import { i2osp, prepare_sjcl_random_generator } from '../src/util.js';
import { PartiallyBlindRSA, RSAPBSSA, getSuiteByName } from '../src/index.js';
Expand Down Expand Up @@ -78,7 +78,7 @@ test('Parameters', () => {
}
});

describe.each(vectors)('Errors-vec$#', (v: Vector) => {
describe.each(vectors)('Errors-vec%#', (v: Vector) => {
test('non-extractable-keys', async () => {
const { privateKey, publicKey } = await keysFromVector(v, false);
const msg = crypto.getRandomValues(new Uint8Array(10));
Expand Down Expand Up @@ -124,20 +124,24 @@ describe.each(vectors)('Errors-vec$#', (v: Vector) => {
});
});

test.each(vectors)('TestVector_$#/safePrimes', (v: Vector) => {
prepare_sjcl_random_generator();
expect(isSafePrime(new sjcl.bn(v.p))).toBe(true);
expect(isSafePrime(new sjcl.bn(v.q))).toBe(true);
});

describe.each(vectors)('TestVector_$#', (v: Vector) => {
test.each(vectors)(
'TestVector_%#/safePrimes',
(v: Vector) => {
prepare_sjcl_random_generator();
expect(isSafePrime(new sjcl.bn(v.p))).toBe(true);
expect(isSafePrime(new sjcl.bn(v.q))).toBe(true);
},
60_000,
);

describe.each(vectors)('TestVector_%#', (v: Vector) => {
beforeEach(() => {
const n = new sjcl.bn(v.n);
const kLen = Math.ceil(n.bitLength() / 8);
const r = new sjcl.bn(v.r);
const rBytes = i2osp(r, kLen);

jest.spyOn(crypto, 'getRandomValues')
vi.spyOn(crypto, 'getRandomValues')
.mockReturnValueOnce(hexToUint8(v.msg_prefix)) // mock msg_prefix
.mockReturnValueOnce(hexToUint8(v.salt)) // mock for random salt
.mockReturnValueOnce(rBytes); // mock for random blind
Expand All @@ -146,37 +150,27 @@ describe.each(vectors)('TestVector_$#', (v: Vector) => {
const all_params = [undefined, { supportsRSARAW: true }];

describe.each(all_params)(`_${v.name}`, (params) => {
test(
`supportsRSARAW/${params ? params.supportsRSARAW : false}`,
async () => {
const blindRSA = getSuiteByName(PartiallyBlindRSA, v.name, params);
expect(blindRSA.toString()).toBe(v.name);

const msg = hexToUint8(v.msg);
const info = hexToUint8(v.info);
const inputMsg = blindRSA.prepare(msg);

const { publicKey, privateKey } = await keysFromVector(v, true);

const { blindedMsg, inv } = await blindRSA.blind(publicKey, inputMsg, info);
expect(uint8ToHex(blindedMsg)).toBe(v.blind_msg);

const blindedSig = await blindRSA.blindSign(privateKey, blindedMsg, info);
expect(uint8ToHex(blindedSig)).toBe(v.blind_sig);

const signature = await blindRSA.finalize(
publicKey,
inputMsg,
info,
blindedSig,
inv,
);
expect(uint8ToHex(signature)).toBe(v.sig);

const isValid = await blindRSA.verify(publicKey, signature, inputMsg, info);
expect(isValid).toBe(true);
},
20 * 1000,
);
test(`supportsRSARAW/${params ? params.supportsRSARAW : false}`, async () => {
const blindRSA = getSuiteByName(PartiallyBlindRSA, v.name, params);
expect(blindRSA.toString()).toBe(v.name);

const msg = hexToUint8(v.msg);
const info = hexToUint8(v.info);
const inputMsg = blindRSA.prepare(msg);

const { publicKey, privateKey } = await keysFromVector(v, true);

const { blindedMsg, inv } = await blindRSA.blind(publicKey, inputMsg, info);
expect(uint8ToHex(blindedMsg)).toBe(v.blind_msg);

const blindedSig = await blindRSA.blindSign(privateKey, blindedMsg, info);
expect(uint8ToHex(blindedSig)).toBe(v.blind_sig);

const signature = await blindRSA.finalize(publicKey, inputMsg, info, blindedSig, inv);
expect(uint8ToHex(signature)).toBe(v.sig);

const isValid = await blindRSA.verify(publicKey, signature, inputMsg, info);
expect(isValid).toBe(true);
}, 300_000);
});
});
34 changes: 21 additions & 13 deletions test/primes.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) 2024 Cloudflare, Inc.
// Licensed under the Apache-2.0 license found in the LICENSE file or at https://opensource.org/licenses/Apache-2.0

import { jest } from '@jest/globals';
import { beforeEach, describe, expect, test, vi } from 'vitest';

import sjcl from '../src/sjcl/index.js';
import { prepare_sjcl_random_generator } from '../src/util.js';
Expand Down Expand Up @@ -78,27 +78,35 @@ test.each(SAFE_PRIMES)('isSafePrime/%#', (p) => {
expect(isSafePrime(new sjcl.bn(p))).toBe(true);
});

test.each([128, 256, 512, 1024])('generatePrime/%p', (bitLength) => {
const p = generatePrime(bitLength);
test.each([128, 256, 512, 1024])(
'generatePrime/%d',
(bitLength) => {
const p = generatePrime(bitLength);

expect(p.bitLength()).toBeGreaterThanOrEqual(bitLength);
expect(isPrime(p)).toBe(true);
});
expect(p.bitLength()).toBeGreaterThanOrEqual(bitLength);
expect(isPrime(p)).toBe(true);
},
1_200_000,
);

test.each([128, 256])('generateSafePrime/%p', (bitLength) => {
const p = generateSafePrime(bitLength);
test.each([128, 256])(
'generateSafePrime/%d',
(bitLength) => {
const p = generateSafePrime(bitLength);

expect(p.bitLength()).toBeGreaterThanOrEqual(bitLength);
expect(isSafePrime(p)).toBe(true);
});
expect(p.bitLength()).toBeGreaterThanOrEqual(bitLength);
expect(isSafePrime(p)).toBe(true);
},
1_200_000,
);

describe('max_num_iterations', () => {
test('generatePrime', () => {
// it always returns 1, which is not a prime
jest.spyOn(sjcl.bn, 'random').mockReturnValue(new sjcl.bn(1));
vi.spyOn(sjcl.bn, 'random').mockReturnValue(new sjcl.bn(1));

expect(() => {
generatePrime(8);
}).toThrow(/MAX_NUM_TRIES/);
});
}, 60_000);
});
File renamed without changes.
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"noUnusedParameters": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"moduleResolution": "bundler",
"esModuleInterop": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
Expand Down
9 changes: 9 additions & 0 deletions vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
dir: './test',
setupFiles: ['./test/vitest.setup-file.ts'],
coverage: { enabled: true },
}
})
Loading