Skip to content

Commit ade9251

Browse files
chore(wasm): Improve tests (#366)
modernize tests in the wasm wrapper.
1 parent 788d489 commit ade9251

File tree

11 files changed

+374
-5156
lines changed

11 files changed

+374
-5156
lines changed

wrappers/wasm/tests/README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
# devolutions-crypto
22
[![Build Status](https://dev.azure.com/devolutions-net/Open%20Source/_apis/build/status/devolutions-crypto?branchName=master)](https://dev.azure.com/devolutions-net/Open%20Source/_build/latest?definitionId=170&branchName=master) [![npm version](https://img.shields.io/npm/v/devolutions-crypto.svg?style=flat)](https://npmjs.org/package/devolutions-crypto "View this project on npm")
33

4-
This folder contains the Javascript/Typescript unit tests for the library. You can also use them as usage example.
4+
This folder contains the TypeScript unit tests for the library. You can also use them as usage examples.
5+
6+
## Test Framework
7+
8+
Tests use the **Node.js native test runner** with TypeScript support via `tsx`. This provides a modern, zero-dependency testing solution with built-in assertions.
9+
10+
## Build Native Library
511

6-
# Build native library
712
```bash
813
cd ..
914
./wasm_build.sh
1015
```
1116

12-
# Run tests
17+
## Run Tests
18+
1319
```bash
20+
# Run all tests
1421
npm test
15-
```
22+
23+
# Run tests in watch mode
24+
npm run test:watch
25+
```
26+
27+
## Test Files
28+
29+
- `asymmetric.ts` - Asymmetric encryption and key exchange tests
30+
- `conformity.ts` - Cross-language compatibility tests
31+
- `hashing.ts` - Password hashing tests
32+
- `secret-sharing.ts` - Shamir's Secret Sharing tests
33+
- `signature.ts` - Digital signature tests
34+
- `symmetric.ts` - Symmetric encryption tests
35+
- `utils.ts` - Key generation, derivation, and encoding tests

wrappers/wasm/tests/package-lock.json

Lines changed: 180 additions & 4986 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

wrappers/wasm/tests/package.json

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
"name": "devolutions-crypto-tests",
33
"version": "1.0.0",
44
"description": "Tests for the devolutions cryptographic library",
5-
"main": "./src/bootstrap.js",
5+
"type": "module",
66
"scripts": {
7-
"test": "mocha -r tsx tests/**.ts",
8-
"fmt": "eslint tests/**.ts --fix"
7+
"test": "tsx --test tests/asymmetric.ts tests/conformity.ts tests/hashing.ts tests/secret-sharing.ts tests/signature.ts tests/symmetric.ts tests/utils.ts",
8+
"test:watch": "tsx --test --watch tests/*.ts"
99
},
1010
"repository": {
1111
"type": "git",
@@ -18,20 +18,8 @@
1818
},
1919
"homepage": "https://github.com/Devolutions/devolutions-crypto#readme",
2020
"devDependencies": {
21-
"@types/chai": "^5.2.0",
22-
"@types/jest": "^29.5.14",
23-
"@types/mocha": "^10.0.10",
24-
"@typescript-eslint/eslint-plugin": "^2.23.0",
25-
"@typescript-eslint/parser": "^2.23.0",
26-
"chai": "^5.2.0",
21+
"@types/node": "^22.10.0",
2722
"devolutions-crypto": "file:../dist/node/",
28-
"eslint": "^6.8.0",
29-
"eslint-config-standard": "^14.1.0",
30-
"eslint-plugin-import": "^2.20.1",
31-
"eslint-plugin-node": "^11.0.0",
32-
"eslint-plugin-promise": "^4.2.1",
33-
"eslint-plugin-standard": "^4.0.1",
34-
"mocha": "^11.1.0",
3523
"tsx": "^4.19.3",
3624
"typescript": "^5.8.2"
3725
}

wrappers/wasm/tests/tests/asymmetric.ts

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,66 +2,66 @@ import {
22
KeyPair, PublicKey, PrivateKey, Argon2Parameters,
33
generateKey, generateKeyPair, encryptAsymmetric, decryptAsymmetric, mixKeyExchange
44
} from 'devolutions-crypto'
5-
import { expect } from 'chai'
6-
import { describe, it } from 'mocha'
5+
import { describe, test } from 'node:test'
6+
import assert from 'node:assert/strict'
77

88
const encoder: TextEncoder = new TextEncoder()
99

1010
describe('generateKeyPair', () => {
11-
it('should generate a random keypair', () => {
11+
test('should generate a random keypair', () => {
1212
const keypair: KeyPair = generateKeyPair()
13-
expect(keypair.private.bytes).to.not.have.lengthOf(0)
14-
expect(keypair.public.bytes).to.not.have.lengthOf(0)
15-
expect(keypair.private).to.not.eql(keypair.public)
13+
assert.notStrictEqual(keypair.private.bytes.length, 0)
14+
assert.notStrictEqual(keypair.public.bytes.length, 0)
15+
assert.notDeepStrictEqual(keypair.private, keypair.public)
1616
})
1717
})
1818

1919
describe('asymmetricEncrypt/asymmetricDecrypt', () => {
20-
it('should be able to encrypt and decrypt', () => {
20+
test('should be able to encrypt and decrypt', () => {
2121
const input: Uint8Array = encoder.encode('This is some test data')
2222
const keypair: KeyPair = generateKeyPair()
2323
const encrypted: Uint8Array = encryptAsymmetric(input, keypair.public)
2424
const decrypted: Uint8Array = decryptAsymmetric(encrypted, keypair.private)
25-
expect(encrypted).to.not.contains(input)
26-
expect(decrypted).to.eql(input)
25+
assert.notDeepStrictEqual(encrypted, input)
26+
assert.deepStrictEqual(decrypted, input)
2727
})
2828

29-
it('should be able to encrypt and decrypt with an AAD', () => {
29+
test('should be able to encrypt and decrypt with an AAD', () => {
3030
const input: Uint8Array = encoder.encode('This is some test data')
3131
const aad: Uint8Array = encoder.encode('This is some public data')
3232
const keypair: KeyPair = generateKeyPair()
3333
const encrypted: Uint8Array = encryptAsymmetric(input, keypair.public, aad)
3434
const decrypted: Uint8Array = decryptAsymmetric(encrypted, keypair.private, aad)
35-
expect(encrypted).to.not.contains(input)
36-
expect(decrypted).to.eql(input)
35+
assert.notDeepStrictEqual(encrypted, input)
36+
assert.deepStrictEqual(decrypted, input)
3737
})
3838

39-
it('should fail if AAD is invalid', () => {
39+
test('should fail if AAD is invalid', () => {
4040
const input: Uint8Array = encoder.encode('This is some test data')
4141
const aad: Uint8Array = encoder.encode('This is some public data')
4242
const wrongAad: Uint8Array = encoder.encode('this is some public data')
4343
const keypair: KeyPair = generateKeyPair()
4444
const encrypted: Uint8Array = encryptAsymmetric(input, keypair.public, aad)
4545

46-
expect(() => decryptAsymmetric(encrypted, keypair.private)).to.throw()
47-
expect(() => decryptAsymmetric(encrypted, keypair.private, wrongAad)).to.throw()
46+
assert.throws(() => decryptAsymmetric(encrypted, keypair.private))
47+
assert.throws(() => decryptAsymmetric(encrypted, keypair.private, wrongAad))
4848
})
4949
})
5050

5151
describe('mixKeyExchange', () => {
52-
it('should give the same 32 byte shared key', () => {
52+
test('should give the same 32 byte shared key', () => {
5353
const bobKeyPair: KeyPair = generateKeyPair()
5454
const aliceKeyPair: KeyPair = generateKeyPair()
5555

5656
const bobShared: Uint8Array = mixKeyExchange(bobKeyPair.private, aliceKeyPair.public)
5757
const aliceShared: Uint8Array = mixKeyExchange(aliceKeyPair.private, bobKeyPair.public)
5858

59-
expect(bobShared).to.have.lengthOf(32)
60-
expect(bobShared).to.not.eql(new Array(32).fill(0))
61-
expect(bobShared).to.eql(aliceShared)
59+
assert.strictEqual(bobShared.length, 32)
60+
assert.notDeepStrictEqual(bobShared, new Uint8Array(32))
61+
assert.deepStrictEqual(bobShared, aliceShared)
6262
})
6363

64-
it('should not give the same 32 byte shared key', () => {
64+
test('should not give the same 32 byte shared key', () => {
6565
const bobKeyPair: KeyPair = generateKeyPair()
6666
const aliceKeyPair: KeyPair = generateKeyPair()
6767
const eveKeyPair: KeyPair = generateKeyPair()
@@ -72,36 +72,36 @@ describe('mixKeyExchange', () => {
7272
const eveBobShared: Uint8Array = mixKeyExchange(eveKeyPair.private, bobKeyPair.public)
7373
const eveAliceShared: Uint8Array = mixKeyExchange(eveKeyPair.private, aliceKeyPair.public)
7474

75-
expect(eveBobShared).to.not.eql(bobShared)
76-
expect(eveBobShared).to.not.eql(aliceShared)
77-
expect(eveAliceShared).to.not.eql(bobShared)
78-
expect(eveAliceShared).to.not.eql(aliceShared)
75+
assert.notDeepStrictEqual(eveBobShared, bobShared)
76+
assert.notDeepStrictEqual(eveBobShared, aliceShared)
77+
assert.notDeepStrictEqual(eveAliceShared, bobShared)
78+
assert.notDeepStrictEqual(eveAliceShared, aliceShared)
7979
})
8080
})
8181

8282
describe('KeyPair serialization', () => {
83-
it('should return the same keypair', () => {
83+
test('should return the same keypair', () => {
8484
const keypair = generateKeyPair()
8585
const privateKeyBytes: Uint8Array = keypair.private.bytes
8686
const publicKeyBytes: Uint8Array = keypair.public.bytes
8787

8888
const privateKey: PrivateKey = PrivateKey.fromBytes(privateKeyBytes)
8989
const publicKey: PublicKey = PublicKey.fromBytes(publicKeyBytes)
9090

91-
expect(privateKey.bytes).to.eql(privateKeyBytes)
92-
expect(publicKey.bytes).to.eql(publicKeyBytes)
91+
assert.deepStrictEqual(privateKey.bytes, privateKeyBytes)
92+
assert.deepStrictEqual(publicKey.bytes, publicKeyBytes)
9393
})
9494

95-
it('should not allow to parse a public key as a private key and vis-versa', () => {
95+
test('should not allow to parse a public key as a private key and vis-versa', () => {
9696
const keypair = generateKeyPair()
9797
const privateKeyBytes: Uint8Array = keypair.private.bytes
9898
const publicKeyBytes: Uint8Array = keypair.public.bytes
9999

100100
const symmetricKey: Uint8Array = generateKey()
101101

102-
expect(() => PrivateKey.fromBytes(publicKeyBytes)).to.throw()
103-
expect(() => PublicKey.fromBytes(privateKeyBytes)).to.throw()
104-
expect(() => PrivateKey.fromBytes(symmetricKey)).to.throw()
105-
expect(() => PublicKey.fromBytes(symmetricKey)).to.throw()
102+
assert.throws(() => PrivateKey.fromBytes(publicKeyBytes))
103+
assert.throws(() => PublicKey.fromBytes(privateKeyBytes))
104+
assert.throws(() => PrivateKey.fromBytes(symmetricKey))
105+
assert.throws(() => PublicKey.fromBytes(symmetricKey))
106106
})
107107
})

wrappers/wasm/tests/tests/conformity.ts

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,98 +2,98 @@
22
import {
33
KeyPair, deriveKeyPbkdf2, base64encode, base64decode, decrypt, Argon2Parameters, PrivateKey, SigningPublicKey, decryptAsymmetric, verifyPassword, verifySignature, deriveKeyArgon2
44
} from 'devolutions-crypto'
5-
import { expect } from 'chai'
6-
import { describe, it } from 'mocha'
5+
import { describe, test } from 'node:test'
6+
import assert from 'node:assert/strict'
77

88
const encoder: TextEncoder = new TextEncoder()
99
const decoder: TextDecoder = new TextDecoder()
1010

1111
describe('Conformity Tests', () => {
12-
it('Key Derivation PBKDF2', () => {
12+
test('Key Derivation PBKDF2', () => {
1313
const derivedKey: Uint8Array = deriveKeyPbkdf2(encoder.encode('testpassword'))
1414
const derivedKeyWithIterations: Uint8Array = deriveKeyPbkdf2(encoder.encode('testPa$$'), null, 100)
1515
const derivedKeyWithSalt: Uint8Array = deriveKeyPbkdf2(encoder.encode('testPa$$'), base64decode('tdTt5wgeqQYLvkiXKkFirqy2hMbzadBtL+jekVeNCRA='), 100)
1616

17-
expect(base64encode(derivedKey)).to.eql('ImfGCyv6PwMYaJShGxR4MfVrjuUrsI0CSarJgOApwf8=')
18-
expect(base64encode(derivedKeyWithIterations)).to.eql('ev/GiJLvOgIkkWrnIrHSi2fdZE5qJBIrW+DLeMLIXK4=')
19-
expect(base64encode(derivedKeyWithSalt)).to.eql('ZaYRZeQiIPJ+Jl511AgHZjv4/HbCFq4eUP9yNa3gowI=')
17+
assert.strictEqual(base64encode(derivedKey), 'ImfGCyv6PwMYaJShGxR4MfVrjuUrsI0CSarJgOApwf8=')
18+
assert.strictEqual(base64encode(derivedKeyWithIterations), 'ev/GiJLvOgIkkWrnIrHSi2fdZE5qJBIrW+DLeMLIXK4=')
19+
assert.strictEqual(base64encode(derivedKeyWithSalt), 'ZaYRZeQiIPJ+Jl511AgHZjv4/HbCFq4eUP9yNa3gowI=')
2020
})
2121

22-
it('Key Derivation Argon2', () => {
22+
test('Key Derivation Argon2', () => {
2323
const parameters: Argon2Parameters = Argon2Parameters.fromBytes(base64decode('AQAAACAAAAABAAAAIAAAAAEAAAACEwAAAAAQAAAAimFBkm3f8+f+YfLRnF5OoQ=='))
2424
const result: Uint8Array = deriveKeyArgon2(encoder.encode('password'), parameters)
2525

26-
expect(base64encode(result)).to.eql('AcEN6Cb1Om6tomZScAM725qiXMzaxaHlj3iMiT/Ukq0=')
26+
assert.strictEqual(base64encode(result), 'AcEN6Cb1Om6tomZScAM725qiXMzaxaHlj3iMiT/Ukq0=')
2727
})
2828

29-
it('Symmetric Decrypt V1', () => {
29+
test('Symmetric Decrypt V1', () => {
3030
const key: Uint8Array = base64decode('ozJVEme4+5e/4NG3C+Rl26GQbGWAqGc0QPX8/1xvaFM=')
3131
const ciphertext: Uint8Array = base64decode('DQwCAAAAAQCK1twEut+TeJfFbTWCRgHjyS6bOPOZUEQAeBtSFFRl2jHggM/34n68zIZWGbsZHkufVzU6mTN5N2Dx9bTplrycv5eNVevT4P9FdVHJ751D+A==')
3232

3333
const decrypted: Uint8Array = decrypt(ciphertext, key)
3434

35-
expect(decoder.decode(decrypted)).to.eql('test Ciph3rtext~')
35+
assert.strictEqual(decoder.decode(decrypted), 'test Ciph3rtext~')
3636
})
3737

38-
it('Symmetric Decrypt with AAD V1', () => {
38+
test('Symmetric Decrypt with AAD V1', () => {
3939
const key: Uint8Array = base64decode('ozJVEme4+5e/4NG3C+Rl26GQbGWAqGc0QPX8/1xvaFM=')
4040
const ciphertext: Uint8Array = base64decode('DQwCAAEAAQCeKfbTqYjfVCEPEiAJjiypBstPmZz0AnpliZKoR+WXTKdj2f/4ops0++dDBVZ+XdyE1KfqxViWVc9djy/HSCcPR4nDehtNI69heGCIFudXfQ==')
4141
const aad: Uint8Array = encoder.encode('this is some public data')
4242

4343
const decrypted: Uint8Array = decrypt(ciphertext, key, aad)
4444

45-
expect(decoder.decode(decrypted)).to.eql('test Ciph3rtext~')
45+
assert.strictEqual(decoder.decode(decrypted), 'test Ciph3rtext~')
4646
})
4747

48-
it('Symmetric Decrypt V2', () => {
48+
test('Symmetric Decrypt V2', () => {
4949
const key: Uint8Array = base64decode('ozJVEme4+5e/4NG3C+Rl26GQbGWAqGc0QPX8/1xvaFM=')
5050
const ciphertext: Uint8Array = base64decode('DQwCAAAAAgAA0iPpI4IEzcrWAQiy6tqDqLbRYduGvlMC32mVH7tpIN2CXDUu5QHF91I7pMrmjt/61pm5CeR/IcU=')
5151

5252
const decrypted: Uint8Array = decrypt(ciphertext, key)
5353

54-
expect(decoder.decode(decrypted)).to.eql('test Ciph3rtext~2')
54+
assert.strictEqual(decoder.decode(decrypted), 'test Ciph3rtext~2')
5555
})
5656

57-
it('Symmetric Decrypt with AAD V2', () => {
57+
test('Symmetric Decrypt with AAD V2', () => {
5858
const key: Uint8Array = base64decode('ozJVEme4+5e/4NG3C+Rl26GQbGWAqGc0QPX8/1xvaFM=')
5959
const ciphertext: Uint8Array = base64decode('DQwCAAEAAgA9bh989dao0Pvaz1NpJTI5m7M4br2qVjZtFwXXoXZOlkCjtqU/uif4pbNCcpEodzeP4YG1QvfKVQ==')
6060
const aad: Uint8Array = encoder.encode('this is some public data')
6161

6262
const decrypted: Uint8Array = decrypt(ciphertext, key, aad)
6363

64-
expect(decoder.decode(decrypted)).to.eql('test Ciph3rtext~')
64+
assert.strictEqual(decoder.decode(decrypted), 'test Ciph3rtext~')
6565
})
6666

67-
it('Asymmetric Decrypt V2', () => {
67+
test('Asymmetric Decrypt V2', () => {
6868
const privateKey: PrivateKey = PrivateKey.fromBytes(base64decode('DQwBAAEAAQAAwQ3oJvU6bq2iZlJwAzvbmqJczNrFoeWPeIyJP9SSbQ=='))
6969
const result: Uint8Array = decryptAsymmetric(base64decode('DQwCAAIAAgCIG9L2MTiumytn7H/p5I3aGVdhV3WUL4i8nIeMWIJ1YRbNQ6lEiQDAyfYhbs6gg1cD7+5Ft2Q5cm7ArsGfiFYWnscm1y7a8tAGfjFFTonzrg=='), privateKey)
7070

71-
expect(decoder.decode(result)).to.eql('testdata')
71+
assert.strictEqual(decoder.decode(result), 'testdata')
7272
})
7373

74-
it('Asymmetric Decrypt V2 with AAD', () => {
74+
test('Asymmetric Decrypt V2 with AAD', () => {
7575
const privateKey: PrivateKey = PrivateKey.fromBytes(base64decode('DQwBAAEAAQC9qf9UY1ovL/48ALGHL9SLVpVozbdjYsw0EPerUl3zYA=='))
7676
const aad: Uint8Array = encoder.encode('this is some public data')
7777

7878
const result: Uint8Array = decryptAsymmetric(base64decode('DQwCAAIAAgB1u62xYeyppWf83QdWwbwGUt5QuiAFZr+hIiFEvMRbXiNCE3RMBNbmgQkLr/vME0BeQa+uUTXZARvJcyNXHyAE4tSdw6o/psU/kw/Z/FbsPw=='), privateKey, aad)
7979

80-
expect(decoder.decode(result)).to.eql('testdata')
80+
assert.strictEqual(decoder.decode(result), 'testdata')
8181
})
8282

83-
it('Password Hashing V1', () => {
83+
test('Password Hashing V1', () => {
8484
const hash1: Uint8Array = base64decode('DQwDAAAAAQAQJwAAXCzLFoyeZhFSDYBAPiIWhCk04aoP/lalOoCl7D+skIY/i+3WT7dn6L8WvnfEq6flCd7i+IcKb3GEK4rCpzhDlw==')
8585
const hash2: Uint8Array = base64decode('DQwDAAAAAQAKAAAAmH1BBckBJYDD0xfiwkAk1xwKgw8a57YQT0Igm+Faa9LFamTeEJgqn/qHc2R/8XEyK2iLPkVy+IErdGLLtLKJ2g==')
86-
expect(verifyPassword(encoder.encode('password1'), hash1)).to.eql(true)
87-
expect(verifyPassword(encoder.encode('password1'), hash2)).to.eql(true)
86+
assert.strictEqual(verifyPassword(encoder.encode('password1'), hash1), true)
87+
assert.strictEqual(verifyPassword(encoder.encode('password1'), hash2), true)
8888
})
8989

90-
it('Signature V1', () => {
90+
test('Signature V1', () => {
9191
const public_key_bytes: Uint8Array = base64decode('DQwFAAIAAQDeEvwlEigK5AXoTorhmlKP6+mbiUU2rYrVQ25JQ5xang==')
9292
const signature: Uint8Array = base64decode('DQwGAAAAAQD82uRk4sFC8vEni6pDNw/vOdN1IEDg9cAVfprWJZ/JBls9Gi61cUt5u6uBJtseNGZFT7qKLvp4NUZrAOL8FH0K')
9393

9494
const public_key = SigningPublicKey.fromBytes(public_key_bytes);
9595

96-
expect(verifySignature(encoder.encode('this is a test'), public_key, signature)).to.eql(true)
97-
expect(verifySignature(encoder.encode('this is wrong'), public_key, signature)).to.eql(false)
96+
assert.strictEqual(verifySignature(encoder.encode('this is a test'), public_key, signature), true)
97+
assert.strictEqual(verifySignature(encoder.encode('this is wrong'), public_key, signature), false)
9898
})
9999
})
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import { hashPassword, verifyPassword } from 'devolutions-crypto'
2-
import { expect } from 'chai'
3-
import { describe, it } from 'mocha'
2+
import { describe, test } from 'node:test'
3+
import assert from 'node:assert/strict'
44

55
const encoder: TextEncoder = new TextEncoder()
66

77
describe('hashing', () => {
8-
it('should validate the password', () => {
8+
test('should validate the password', () => {
99
const hash: Uint8Array = hashPassword(encoder.encode('password'), 10)
1010

11-
expect(verifyPassword(encoder.encode('password'), hash)).to.eql(true)
11+
assert.strictEqual(verifyPassword(encoder.encode('password'), hash), true)
1212
})
1313

14-
it('should not validate the password', () => {
14+
test('should not validate the password', () => {
1515
const hash: Uint8Array = hashPassword(encoder.encode('password'), 10)
1616

17-
expect(verifyPassword(encoder.encode('pa$$word'), hash)).to.eql(false)
18-
expect(verifyPassword(encoder.encode('Password'), hash)).to.eql(false)
19-
expect(verifyPassword(encoder.encode('password1'), hash)).to.eql(false)
17+
assert.strictEqual(verifyPassword(encoder.encode('pa$$word'), hash), false)
18+
assert.strictEqual(verifyPassword(encoder.encode('Password'), hash), false)
19+
assert.strictEqual(verifyPassword(encoder.encode('password1'), hash), false)
2020
})
2121
})

0 commit comments

Comments
 (0)