cojson 0.13.28 โ 0.13.30
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.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +14 -0
- package/dist/coValueCore/coValueCore.d.ts +1 -0
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +17 -2
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValues/coPlainText.d.ts +0 -1
- package/dist/coValues/coPlainText.d.ts.map +1 -1
- package/dist/coValues/coPlainText.js +10 -10
- package/dist/coValues/coPlainText.js.map +1 -1
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +1 -1
- package/dist/coValues/group.js.map +1 -1
- package/dist/crypto/PureJSCrypto.d.ts +1 -1
- package/dist/crypto/PureJSCrypto.js +3 -3
- package/dist/crypto/PureJSCrypto.js.map +1 -1
- package/dist/exports.d.ts +1 -0
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +3 -0
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +7 -1
- package/dist/localNode.js.map +1 -1
- package/dist/tests/coPlainText.test.js +68 -10
- package/dist/tests/coPlainText.test.js.map +1 -1
- package/dist/tests/crypto.test.js +5 -5
- package/dist/tests/crypto.test.js.map +1 -1
- package/dist/tests/group.addMember.test.d.ts +2 -0
- package/dist/tests/group.addMember.test.d.ts.map +1 -0
- package/dist/tests/group.addMember.test.js +272 -0
- package/dist/tests/group.addMember.test.js.map +1 -0
- package/dist/tests/testUtils.d.ts +1 -1
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/coValueCore/coValueCore.ts +21 -2
- package/src/coValues/coPlainText.ts +10 -19
- package/src/coValues/group.ts +3 -6
- package/src/crypto/PureJSCrypto.ts +3 -3
- package/src/exports.ts +3 -0
- package/src/localNode.ts +11 -3
- package/src/tests/coPlainText.test.ts +79 -18
- package/src/tests/crypto.test.ts +5 -5
- package/src/tests/group.addMember.test.ts +432 -0
- package/src/tests/testUtils.ts +6 -6
package/package.json
CHANGED
|
@@ -25,20 +25,21 @@
|
|
|
25
25
|
},
|
|
26
26
|
"type": "module",
|
|
27
27
|
"license": "MIT",
|
|
28
|
-
"version": "0.13.
|
|
28
|
+
"version": "0.13.30",
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@opentelemetry/sdk-metrics": "^2.0.0",
|
|
31
31
|
"typescript": "5.6.2"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@noble/ciphers": "^
|
|
35
|
-
"@noble/curves": "^1.
|
|
36
|
-
"@noble/hashes": "^1.
|
|
34
|
+
"@noble/ciphers": "^1.3.0",
|
|
35
|
+
"@noble/curves": "^1.9.1",
|
|
36
|
+
"@noble/hashes": "^1.8.0",
|
|
37
37
|
"@opentelemetry/api": "^1.9.0",
|
|
38
38
|
"@scure/base": "1.2.1",
|
|
39
39
|
"jazz-crypto-rs": "0.0.7",
|
|
40
40
|
"neverthrow": "^7.0.1",
|
|
41
|
-
"queueueue": "^4.1.2"
|
|
41
|
+
"queueueue": "^4.1.2",
|
|
42
|
+
"unicode-segmenter": "^0.12.0"
|
|
42
43
|
},
|
|
43
44
|
"gitHead": "33c27053293b4801b968c61d5c4c989f93a67d13",
|
|
44
45
|
"scripts": {
|
|
@@ -67,7 +67,7 @@ export type AvailableCoValueCore = CoValueCore & { verified: VerifiedState };
|
|
|
67
67
|
export const CO_VALUE_LOADING_CONFIG = {
|
|
68
68
|
MAX_RETRIES: 1,
|
|
69
69
|
TIMEOUT: 30_000,
|
|
70
|
-
RETRY_DELAY:
|
|
70
|
+
RETRY_DELAY: 3000,
|
|
71
71
|
};
|
|
72
72
|
|
|
73
73
|
export class CoValueCore {
|
|
@@ -193,6 +193,20 @@ export class CoValueCore {
|
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
+
waitForAvailable(): Promise<CoValueCore> {
|
|
197
|
+
return new Promise<CoValueCore>((resolve) => {
|
|
198
|
+
const listener = (core: CoValueCore) => {
|
|
199
|
+
if (core.isAvailable()) {
|
|
200
|
+
resolve(core);
|
|
201
|
+
this.listeners.delete(listener);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
this.listeners.add(listener);
|
|
206
|
+
listener(this);
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
|
|
196
210
|
getStateForPeer(peerId: PeerID) {
|
|
197
211
|
return this.peers.get(peerId);
|
|
198
212
|
}
|
|
@@ -1030,6 +1044,11 @@ export class CoValueCore {
|
|
|
1030
1044
|
});
|
|
1031
1045
|
peer.trackLoadRequestSent(this.id);
|
|
1032
1046
|
|
|
1047
|
+
const timeoutDuration =
|
|
1048
|
+
peer.role === "storage"
|
|
1049
|
+
? CO_VALUE_LOADING_CONFIG.TIMEOUT * 10
|
|
1050
|
+
: CO_VALUE_LOADING_CONFIG.TIMEOUT;
|
|
1051
|
+
|
|
1033
1052
|
return new Promise<void>((resolve) => {
|
|
1034
1053
|
const markNotFound = () => {
|
|
1035
1054
|
if (this.peers.get(peer.id)?.type === "pending") {
|
|
@@ -1041,7 +1060,7 @@ export class CoValueCore {
|
|
|
1041
1060
|
}
|
|
1042
1061
|
};
|
|
1043
1062
|
|
|
1044
|
-
const timeout = setTimeout(markNotFound,
|
|
1063
|
+
const timeout = setTimeout(markNotFound, timeoutDuration);
|
|
1045
1064
|
const removeCloseListener = peer.addCloseListener(markNotFound);
|
|
1046
1065
|
|
|
1047
1066
|
const listener = (state: CoValueCore) => {
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
CoValueCore,
|
|
4
|
-
} from "../coValueCore/coValueCore.js";
|
|
1
|
+
import { splitGraphemes } from "unicode-segmenter/grapheme";
|
|
2
|
+
import { AvailableCoValueCore } from "../coValueCore/coValueCore.js";
|
|
5
3
|
import { JsonObject } from "../jsonValue.js";
|
|
6
4
|
import { DeletionOpPayload, OpID, RawCoList } from "./coList.js";
|
|
7
5
|
|
|
@@ -57,8 +55,6 @@ export class RawCoPlainText<
|
|
|
57
55
|
/** @category 6. Meta */
|
|
58
56
|
type = "coplaintext" as const;
|
|
59
57
|
|
|
60
|
-
private _segmenter: Intl.Segmenter;
|
|
61
|
-
|
|
62
58
|
_cachedMapping: WeakMap<
|
|
63
59
|
NonNullable<typeof this._cachedEntries>,
|
|
64
60
|
PlaintextIdxMapping
|
|
@@ -67,11 +63,6 @@ export class RawCoPlainText<
|
|
|
67
63
|
constructor(core: AvailableCoValueCore) {
|
|
68
64
|
super(core);
|
|
69
65
|
this._cachedMapping = new WeakMap();
|
|
70
|
-
if (!Intl.Segmenter) {
|
|
71
|
-
throw new Error(
|
|
72
|
-
"Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
66
|
|
|
76
67
|
// Use locale from meta if provided, fallback to browser locale, or 'en' as last resort
|
|
77
68
|
const effectiveLocale =
|
|
@@ -81,10 +72,6 @@ export class RawCoPlainText<
|
|
|
81
72
|
? (core.verified.header.meta.locale as string)
|
|
82
73
|
: undefined) ||
|
|
83
74
|
(typeof navigator !== "undefined" ? navigator.language : "en");
|
|
84
|
-
|
|
85
|
-
this._segmenter = new Intl.Segmenter(effectiveLocale, {
|
|
86
|
-
granularity: "grapheme",
|
|
87
|
-
});
|
|
88
75
|
}
|
|
89
76
|
|
|
90
77
|
get mapping() {
|
|
@@ -104,7 +91,7 @@ export class RawCoPlainText<
|
|
|
104
91
|
let idxBefore = 0;
|
|
105
92
|
|
|
106
93
|
for (const entry of entries) {
|
|
107
|
-
const idxAfter = idxBefore +
|
|
94
|
+
const idxAfter = idxBefore + 1;
|
|
108
95
|
|
|
109
96
|
mapping.opIDafterIdx[idxBefore] = entry.opID;
|
|
110
97
|
mapping.opIDbeforeIdx[idxAfter] = entry.opID;
|
|
@@ -138,7 +125,7 @@ export class RawCoPlainText<
|
|
|
138
125
|
text: string,
|
|
139
126
|
privacy: "private" | "trusting" = "private",
|
|
140
127
|
) {
|
|
141
|
-
const graphemes = [...
|
|
128
|
+
const graphemes = [...splitGraphemes(text)];
|
|
142
129
|
|
|
143
130
|
if (idx === 0) {
|
|
144
131
|
// For insertions at start, prepend each character in reverse
|
|
@@ -164,8 +151,12 @@ export class RawCoPlainText<
|
|
|
164
151
|
text: string,
|
|
165
152
|
privacy: "private" | "trusting" = "private",
|
|
166
153
|
) {
|
|
167
|
-
const graphemes = [...
|
|
168
|
-
this.
|
|
154
|
+
const graphemes = [...splitGraphemes(text)];
|
|
155
|
+
if (idx >= this.entries().length) {
|
|
156
|
+
this.appendItems(graphemes, idx - 1, privacy);
|
|
157
|
+
} else {
|
|
158
|
+
this.appendItems(graphemes, idx, privacy);
|
|
159
|
+
}
|
|
169
160
|
}
|
|
170
161
|
|
|
171
162
|
deleteRange(
|
package/src/coValues/group.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { base58 } from "@scure/base";
|
|
2
2
|
import { CoID } from "../coValue.js";
|
|
3
|
-
import {
|
|
4
|
-
AvailableCoValueCore,
|
|
5
|
-
CoValueCore,
|
|
6
|
-
} from "../coValueCore/coValueCore.js";
|
|
3
|
+
import { AvailableCoValueCore } from "../coValueCore/coValueCore.js";
|
|
7
4
|
import { CoValueUniqueness } from "../coValueCore/verifiedState.js";
|
|
8
5
|
import {
|
|
9
6
|
CryptoProvider,
|
|
@@ -27,7 +24,6 @@ import { logger } from "../logger.js";
|
|
|
27
24
|
import { AccountRole, Role } from "../permissions.js";
|
|
28
25
|
import { expectGroup } from "../typeUtils/expectGroup.js";
|
|
29
26
|
import {
|
|
30
|
-
ControlledAccount,
|
|
31
27
|
ControlledAccountOrAgent,
|
|
32
28
|
RawAccount,
|
|
33
29
|
RawAccountID,
|
|
@@ -332,6 +328,8 @@ export class RawGroup<
|
|
|
332
328
|
if (role === "writeOnly" || role === "writeOnlyInvite") {
|
|
333
329
|
const previousRole = this.get(memberKey);
|
|
334
330
|
|
|
331
|
+
this.set(memberKey, role, "trusting");
|
|
332
|
+
|
|
335
333
|
if (
|
|
336
334
|
previousRole === "reader" ||
|
|
337
335
|
previousRole === "writer" ||
|
|
@@ -340,7 +338,6 @@ export class RawGroup<
|
|
|
340
338
|
this.rotateReadKey();
|
|
341
339
|
}
|
|
342
340
|
|
|
343
|
-
this.set(memberKey, role, "trusting");
|
|
344
341
|
this.internalCreateWriteOnlyKeyForMember(memberKey, agent);
|
|
345
342
|
} else {
|
|
346
343
|
const currentReadKey = this.core.getCurrentReadKey();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { xsalsa20,
|
|
1
|
+
import { xsalsa20, xsalsa20poly1305 } from "@noble/ciphers/salsa";
|
|
2
2
|
import { ed25519, x25519 } from "@noble/curves/ed25519";
|
|
3
3
|
import { blake3 } from "@noble/hashes/blake3";
|
|
4
4
|
import { base58 } from "@scure/base";
|
|
@@ -165,7 +165,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
|
|
|
165
165
|
|
|
166
166
|
const sharedSecret = x25519.getSharedSecret(senderPriv, sealerPub);
|
|
167
167
|
|
|
168
|
-
const sealedBytes =
|
|
168
|
+
const sealedBytes = xsalsa20poly1305(sharedSecret, nOnce).encrypt(
|
|
169
169
|
plaintext,
|
|
170
170
|
);
|
|
171
171
|
|
|
@@ -188,7 +188,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
|
|
|
188
188
|
|
|
189
189
|
const sharedSecret = x25519.getSharedSecret(sealerPriv, senderPub);
|
|
190
190
|
|
|
191
|
-
const plaintext =
|
|
191
|
+
const plaintext = xsalsa20poly1305(sharedSecret, nOnce).decrypt(
|
|
192
192
|
sealedBytes,
|
|
193
193
|
);
|
|
194
194
|
|
package/src/exports.ts
CHANGED
package/src/localNode.ts
CHANGED
|
@@ -345,6 +345,10 @@ export class LocalNode {
|
|
|
345
345
|
while (true) {
|
|
346
346
|
const coValue = this.getCoValue(id);
|
|
347
347
|
|
|
348
|
+
if (coValue.isAvailable()) {
|
|
349
|
+
return coValue;
|
|
350
|
+
}
|
|
351
|
+
|
|
348
352
|
if (
|
|
349
353
|
coValue.loadingState === "unknown" ||
|
|
350
354
|
coValue.loadingState === "unavailable"
|
|
@@ -365,6 +369,7 @@ export class LocalNode {
|
|
|
365
369
|
}
|
|
366
370
|
|
|
367
371
|
const result = await coValue.waitForAvailableOrUnavailable();
|
|
372
|
+
|
|
368
373
|
if (
|
|
369
374
|
result.isAvailable() ||
|
|
370
375
|
retries >= CO_VALUE_LOADING_CONFIG.MAX_RETRIES
|
|
@@ -372,9 +377,12 @@ export class LocalNode {
|
|
|
372
377
|
return result;
|
|
373
378
|
}
|
|
374
379
|
|
|
375
|
-
await
|
|
376
|
-
|
|
377
|
-
|
|
380
|
+
await Promise.race([
|
|
381
|
+
new Promise((resolve) =>
|
|
382
|
+
setTimeout(resolve, CO_VALUE_LOADING_CONFIG.RETRY_DELAY),
|
|
383
|
+
),
|
|
384
|
+
coValue.waitForAvailable(), // Stop waiting if the coValue becomes available
|
|
385
|
+
]);
|
|
378
386
|
|
|
379
387
|
retries++;
|
|
380
388
|
}
|
|
@@ -1,28 +1,12 @@
|
|
|
1
1
|
import { afterEach, expect, test, vi } from "vitest";
|
|
2
2
|
import { expectPlainText } from "../coValue.js";
|
|
3
3
|
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
nodeWithRandomAgentAndSessionID,
|
|
7
|
-
randomAgentAndSessionID,
|
|
8
|
-
} from "./testUtils.js";
|
|
4
|
+
import { nodeWithRandomAgentAndSessionID } from "./testUtils.js";
|
|
9
5
|
|
|
10
6
|
const Crypto = await WasmCrypto.create();
|
|
11
7
|
|
|
12
8
|
afterEach(() => void vi.unstubAllGlobals());
|
|
13
9
|
|
|
14
|
-
test("should throw on creation if Intl.Segmenter is not available", () => {
|
|
15
|
-
vi.stubGlobal("Intl", {
|
|
16
|
-
Segmenter: undefined,
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const node = nodeWithRandomAgentAndSessionID();
|
|
20
|
-
const group = node.createGroup();
|
|
21
|
-
expect(() => group.createPlainText()).toThrow(
|
|
22
|
-
"Intl.Segmenter is not supported. Use a polyfill to get coPlainText support in Jazz. (eg. https://formatjs.github.io/docs/polyfills/intl-segmenter/)",
|
|
23
|
-
);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
10
|
test("Empty CoPlainText works", () => {
|
|
27
11
|
const node = nodeWithRandomAgentAndSessionID();
|
|
28
12
|
|
|
@@ -86,7 +70,7 @@ test("Can insert and delete in CoPlainText", () => {
|
|
|
86
70
|
content.insertBefore(2, "๐", "trusting");
|
|
87
71
|
expect(content.toString()).toEqual("He๐llo, world");
|
|
88
72
|
|
|
89
|
-
content.deleteRange({ from: 2, to:
|
|
73
|
+
content.deleteRange({ from: 2, to: 3 }, "trusting");
|
|
90
74
|
expect(content.toString()).toEqual("Hello, world");
|
|
91
75
|
});
|
|
92
76
|
|
|
@@ -204,3 +188,80 @@ test("insertBefore and insertAfter work as expected", () => {
|
|
|
204
188
|
content.insertBefore(0, "!", "trusting"); // "!hey"
|
|
205
189
|
expect(content.toString()).toEqual("!hey");
|
|
206
190
|
});
|
|
191
|
+
|
|
192
|
+
test("Can delete a single grapheme", () => {
|
|
193
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
194
|
+
const coValue = node.createCoValue({
|
|
195
|
+
type: "coplaintext",
|
|
196
|
+
ruleset: { type: "unsafeAllowAll" },
|
|
197
|
+
meta: null,
|
|
198
|
+
...Crypto.createdNowUnique(),
|
|
199
|
+
});
|
|
200
|
+
const content = expectPlainText(coValue.getCurrentContent());
|
|
201
|
+
|
|
202
|
+
content.insertAfter(0, "aฬeฬoฬฬฒ", "trusting"); // 3 graphemes
|
|
203
|
+
content.deleteRange({ from: 1, to: 2 }, "trusting"); // delete the second grapheme
|
|
204
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ");
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
test("Handles complex grapheme clusters correctly", () => {
|
|
208
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
209
|
+
const coValue = node.createCoValue({
|
|
210
|
+
type: "coplaintext",
|
|
211
|
+
ruleset: { type: "unsafeAllowAll" },
|
|
212
|
+
meta: null,
|
|
213
|
+
...Crypto.createdNowUnique(),
|
|
214
|
+
});
|
|
215
|
+
const content = expectPlainText(coValue.getCurrentContent());
|
|
216
|
+
|
|
217
|
+
// Combining marks (should be treated as one grapheme each)
|
|
218
|
+
const combining = "aฬeฬoฬฬฒ"; // 3 graphemes: [aฬ][eฬ][oฬฬฒ]
|
|
219
|
+
content.insertAfter(0, combining, "trusting");
|
|
220
|
+
expect(content.toString()).toEqual(combining);
|
|
221
|
+
content.deleteRange({ from: 1, to: 2 }, "trusting");
|
|
222
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ");
|
|
223
|
+
|
|
224
|
+
// ZWJ emoji (family)
|
|
225
|
+
const family = "๐จโ๐ฉโ๐งโ๐ฆ"; // 1 grapheme
|
|
226
|
+
content.insertAfter(2, family, "trusting");
|
|
227
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ๐จโ๐ฉโ๐งโ๐ฆ");
|
|
228
|
+
content.deleteRange({ from: 2, to: 3 }, "trusting");
|
|
229
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ");
|
|
230
|
+
|
|
231
|
+
// Flag emoji (regional indicators)
|
|
232
|
+
const flag = "๐บ๐ธ"; // 1 grapheme
|
|
233
|
+
content.insertAfter(2, flag, "trusting");
|
|
234
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ๐บ๐ธ");
|
|
235
|
+
content.deleteRange({ from: 2, to: 3 }, "trusting");
|
|
236
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ");
|
|
237
|
+
|
|
238
|
+
// Emoji with skin tone modifier
|
|
239
|
+
const thumbsUp = "๐๐ฝ"; // 1 grapheme
|
|
240
|
+
content.insertAfter(2, thumbsUp, "trusting");
|
|
241
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ๐๐ฝ");
|
|
242
|
+
content.deleteRange({ from: 2, to: 3 }, "trusting");
|
|
243
|
+
expect(content.toString()).toEqual("aฬoฬฬฒ");
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
test("Handle deletion of complex grapheme clusters correctly", () => {
|
|
247
|
+
const node = nodeWithRandomAgentAndSessionID();
|
|
248
|
+
const coValue = node.createCoValue({
|
|
249
|
+
type: "coplaintext",
|
|
250
|
+
ruleset: { type: "unsafeAllowAll" },
|
|
251
|
+
meta: null,
|
|
252
|
+
...Crypto.createdNowUnique(),
|
|
253
|
+
});
|
|
254
|
+
const content = expectPlainText(coValue.getCurrentContent());
|
|
255
|
+
|
|
256
|
+
// Combining marks (should be treated as one grapheme each)
|
|
257
|
+
content.insertAfter(0, "๐ ์๋
!", "trusting");
|
|
258
|
+
expect(content.toString()).toEqual("๐ ์๋
!");
|
|
259
|
+
|
|
260
|
+
// Delete the first grapheme
|
|
261
|
+
content.deleteRange({ from: 0, to: 1 }, "trusting");
|
|
262
|
+
expect(content.toString()).toEqual(" ์๋
!");
|
|
263
|
+
|
|
264
|
+
// Delete the second grapheme
|
|
265
|
+
content.deleteRange({ from: 1, to: 2 }, "trusting");
|
|
266
|
+
expect(content.toString()).toEqual(" ๋
!");
|
|
267
|
+
});
|
package/src/tests/crypto.test.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { xsalsa20poly1305 } from "@noble/ciphers/salsa";
|
|
2
2
|
import { x25519 } from "@noble/curves/ed25519";
|
|
3
3
|
import { blake3 } from "@noble/hashes/blake3";
|
|
4
4
|
import { base58, base64url } from "@scure/base";
|
|
@@ -68,7 +68,7 @@ const pureJSCrypto = await PureJSCrypto.create();
|
|
|
68
68
|
crypto.getSealerID(sender),
|
|
69
69
|
nOnceMaterial,
|
|
70
70
|
),
|
|
71
|
-
).toThrow(
|
|
71
|
+
).toThrow(name === "PureJSCrypto" ? "invalid tag" : "Wrong tag");
|
|
72
72
|
|
|
73
73
|
// trying with wrong sealer secret, by hand
|
|
74
74
|
const nOnce = blake3(
|
|
@@ -84,8 +84,8 @@ const pureJSCrypto = await PureJSCrypto.create();
|
|
|
84
84
|
const sharedSecret = x25519.getSharedSecret(sealer3priv, senderPub);
|
|
85
85
|
|
|
86
86
|
expect(() => {
|
|
87
|
-
const _ =
|
|
88
|
-
}).toThrow("
|
|
87
|
+
const _ = xsalsa20poly1305(sharedSecret, nOnce).decrypt(sealedBytes);
|
|
88
|
+
}).toThrow("invalid tag");
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
test(`Hashing is deterministic [${name}]`, () => {
|
|
@@ -211,7 +211,7 @@ const pureJSCrypto = await PureJSCrypto.create();
|
|
|
211
211
|
|
|
212
212
|
const plaintext = new TextEncoder().encode(data);
|
|
213
213
|
const sharedSecret = x25519.getSharedSecret(senderPriv, sealerPub);
|
|
214
|
-
const sealedBytes =
|
|
214
|
+
const sealedBytes = xsalsa20poly1305(sharedSecret, nOnce).encrypt(
|
|
215
215
|
plaintext,
|
|
216
216
|
);
|
|
217
217
|
const sealed = `sealed_U${base64url.encode(sealedBytes)}`;
|