@vex-chat/crypto 10.0.0 → 12.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,64 +0,0 @@
1
- /**
2
- * Copyright (c) 2020-2026 Vex Heavy Industries LLC
3
- * Licensed under AGPL-3.0. See LICENSE for details.
4
- * Commercial licenses available at vex.wtf
5
- */
6
-
7
- import {
8
- getCryptoProfile,
9
- setCryptoProfile,
10
- xDH,
11
- xMakeNonce,
12
- xRandomBytes,
13
- XUtils,
14
- } from "../index.js";
15
-
16
- afterEach(() => {
17
- setCryptoProfile("tweetnacl");
18
- });
19
-
20
- test("crypto profile defaults to tweetnacl", () => {
21
- expect(getCryptoProfile()).toBe("tweetnacl");
22
- });
23
-
24
- test("fips profile rejects nacl-coupled operations", () => {
25
- setCryptoProfile("fips");
26
-
27
- const myPrivateKey = XUtils.decodeHex(
28
- "918ed243e2c6c507168b20e8b167cff33a10c30e99e8defe28dc2147f5cce703",
29
- );
30
- const theirPublicKey = XUtils.decodeHex(
31
- "6f4cc1ffc4009bd4f94628ba5922e40afa3491f0daa43ec9da0f7dc39bb1c026",
32
- );
33
-
34
- expect(() => xDH(myPrivateKey, theirPublicKey)).toThrow(
35
- 'Crypto profile "fips" does not implement xDH yet.',
36
- );
37
- });
38
-
39
- test("fips profile still supports random bytes", () => {
40
- setCryptoProfile("fips");
41
-
42
- const bytes = xRandomBytes(32);
43
- const nonce = xMakeNonce();
44
-
45
- expect(bytes.length).toBe(32);
46
- expect(nonce.length).toBe(24);
47
- });
48
-
49
- test("switching back to tweetnacl restores behavior", () => {
50
- const myPrivateKey = XUtils.decodeHex(
51
- "918ed243e2c6c507168b20e8b167cff33a10c30e99e8defe28dc2147f5cce703",
52
- );
53
- const theirPublicKey = XUtils.decodeHex(
54
- "6f4cc1ffc4009bd4f94628ba5922e40afa3491f0daa43ec9da0f7dc39bb1c026",
55
- );
56
- const correctDerivedKey =
57
- "19a8594bdcf875ec9d4b8b9615ea8b73a0b327bb64b8f727dd2dee3a603a2230";
58
-
59
- setCryptoProfile("fips");
60
- setCryptoProfile("tweetnacl");
61
-
62
- const derived = XUtils.encodeHex(xDH(myPrivateKey, theirPublicKey));
63
- expect(derived).toBe(correctDerivedKey);
64
- });
@@ -1,77 +0,0 @@
1
- /**
2
- * Copyright (c) 2020-2026 Vex Heavy Industries LLC
3
- * Licensed under AGPL-3.0. See LICENSE for details.
4
- * Commercial licenses available at vex.wtf
5
- */
6
-
7
- import {
8
- enterCryptoProfileScope,
9
- getCryptoProfile,
10
- leaveCryptoProfileScope,
11
- setCryptoProfile,
12
- xBoxKeyPairAsync,
13
- xDHAsync,
14
- xSecretboxAsync,
15
- xSecretboxOpenAsync,
16
- XUtils,
17
- } from "../index.js";
18
-
19
- afterEach(() => {
20
- setCryptoProfile("tweetnacl");
21
- });
22
-
23
- test("leaveCryptoProfileScope without enter throws", () => {
24
- setCryptoProfile("tweetnacl");
25
- expect(() => {
26
- leaveCryptoProfileScope();
27
- }).toThrow(
28
- /leaveCryptoProfileScope called without a matching enterCryptoProfileScope/,
29
- );
30
- });
31
-
32
- test("nested enter/leave restores outer profile", () => {
33
- setCryptoProfile("tweetnacl");
34
- enterCryptoProfileScope("fips");
35
- expect(getCryptoProfile()).toBe("fips");
36
- enterCryptoProfileScope("fips");
37
- expect(getCryptoProfile()).toBe("fips");
38
- leaveCryptoProfileScope();
39
- expect(getCryptoProfile()).toBe("fips");
40
- leaveCryptoProfileScope();
41
- expect(getCryptoProfile()).toBe("tweetnacl");
42
- });
43
-
44
- test("concurrent fips scopes: overlapping decrypts stay on fips", async () => {
45
- setCryptoProfile("tweetnacl");
46
- enterCryptoProfileScope("fips");
47
- const alice = await xBoxKeyPairAsync();
48
- const bob = await xBoxKeyPairAsync();
49
- const shared = await xDHAsync(alice.secretKey, bob.publicKey);
50
- const nonce = new Uint8Array(24);
51
- nonce.set(crypto.getRandomValues(new Uint8Array(24)));
52
- const plaintext = XUtils.decodeUTF8("concurrent-scope");
53
- const ciphertext = await xSecretboxAsync(plaintext, nonce, shared);
54
- leaveCryptoProfileScope();
55
- expect(getCryptoProfile()).toBe("tweetnacl");
56
-
57
- const decryptOnce = async (delayMs: number): Promise<string> => {
58
- enterCryptoProfileScope("fips");
59
- try {
60
- if (delayMs > 0) {
61
- await new Promise((r) => setTimeout(r, delayMs));
62
- }
63
- const opened = await xSecretboxOpenAsync(ciphertext, nonce, shared);
64
- if (opened === null) {
65
- throw new Error("Expected decrypt under stacked fips scope.");
66
- }
67
- return XUtils.encodeUTF8(opened);
68
- } finally {
69
- leaveCryptoProfileScope();
70
- }
71
- };
72
-
73
- const [a, b] = await Promise.all([decryptOnce(0), decryptOnce(15)]);
74
- expect(a).toBe("concurrent-scope");
75
- expect(b).toBe("concurrent-scope");
76
- expect(getCryptoProfile()).toBe("tweetnacl");
77
- });