@nice-code/util 0.5.5 → 0.6.1

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.
Files changed (30) hide show
  1. package/README.md +165 -73
  2. package/build/index.js +839 -7
  3. package/build/types/core/core_valibot_schemas.d.ts +13 -0
  4. package/build/types/core/createDataStringConverter_stringToObject.d.ts +12 -0
  5. package/build/types/crypto/aes_gcm/createAesGcmKeyFromX25519Keys.d.ts +6 -0
  6. package/build/types/crypto/aes_gcm/decryptBytesWithAesGcmKey.d.ts +9 -0
  7. package/build/types/crypto/aes_gcm/decryptTextDataWithAesGcmKey.d.ts +5 -0
  8. package/build/types/crypto/aes_gcm/encryptBytesWithAesGcmKey.d.ts +10 -0
  9. package/build/types/crypto/aes_gcm/encryptTextDataWithAesGcmKey.d.ts +5 -0
  10. package/build/types/crypto/client_key_link/ClientCryptoKeyLink.d.ts +181 -0
  11. package/build/types/crypto/client_key_link/buildVerifyKeyBoundInfoString.d.ts +20 -0
  12. package/build/types/crypto/crypto.converters.d.ts +53 -0
  13. package/build/types/crypto/crypto.schema.d.ts +92 -0
  14. package/build/types/crypto/ed25519/generateEd25519KeyPair.d.ts +1 -0
  15. package/build/types/crypto/ed25519/importEd25519Key.d.ts +35 -0
  16. package/build/types/crypto/ed25519/serializeEd25519Key_Jwk.d.ts +2 -0
  17. package/build/types/crypto/ed25519/serializeEd25519Key_Raw.d.ts +2 -0
  18. package/build/types/crypto/ed25519/signCombinedTextDataWithKeyEd25519.d.ts +2 -0
  19. package/build/types/crypto/ed25519/signTextDataWithKeyEd25519.d.ts +1 -0
  20. package/build/types/crypto/ed25519/verifyWithKeyEd25519.d.ts +5 -0
  21. package/build/types/crypto/index.d.ts +21 -0
  22. package/build/types/crypto/x25519/createSharedBitsFromX25519.d.ts +4 -0
  23. package/build/types/crypto/x25519/generateX25519KeyPair.d.ts +1 -0
  24. package/build/types/crypto/x25519/importX25519Key.d.ts +35 -0
  25. package/build/types/crypto/x25519/serializeX25519Key_Jwk.d.ts +2 -0
  26. package/build/types/crypto/x25519/serializeX25519Key_Raw.d.ts +2 -0
  27. package/build/types/data_type/index.d.ts +1 -0
  28. package/build/types/data_type/string/nullEmpty.d.ts +3 -0
  29. package/build/types/index.d.ts +2 -0
  30. package/package.json +5 -1
package/build/index.js CHANGED
@@ -1,9 +1,110 @@
1
- // src/storage_adapter/storage_adapter.types.ts
2
- var EStorageAdapterType;
3
- ((EStorageAdapterType2) => {
4
- EStorageAdapterType2["string"] = "string";
5
- EStorageAdapterType2["json"] = "json";
6
- })(EStorageAdapterType ||= {});
1
+ // src/data_type/string/nullEmpty.ts
2
+ var notNullEmpty = (str) => {
3
+ return str != null && str.length > 0;
4
+ };
5
+
6
+ // src/crypto/x25519/createSharedBitsFromX25519.ts
7
+ var createSharedBitsFromX25519 = async ({
8
+ privateKey,
9
+ publicKey
10
+ }) => {
11
+ return new Uint8Array(await crypto.subtle.deriveBits({ name: "X25519", public: publicKey }, privateKey, 256));
12
+ };
13
+
14
+ // src/crypto/aes_gcm/createAesGcmKeyFromX25519Keys.ts
15
+ var DEFAULT_INFO_STRING = "METEOR_BRIDGE_DEFAULT_INFO_STRING";
16
+ var createAesGcmKeyFromX25519Keys = async ({
17
+ externalX25519PublicKey,
18
+ internalX25519PrivateKey,
19
+ infoString,
20
+ saltString
21
+ }) => {
22
+ const sharedBits = await createSharedBitsFromX25519({
23
+ privateKey: internalX25519PrivateKey,
24
+ publicKey: externalX25519PublicKey
25
+ });
26
+ const ikm = await crypto.subtle.importKey("raw", new Uint8Array(sharedBits), "HKDF", false, [
27
+ "deriveKey"
28
+ ]);
29
+ const salt = notNullEmpty(saltString) ? new TextEncoder().encode(saltString) : new Uint8Array;
30
+ const info = new TextEncoder().encode(notNullEmpty(infoString) ? infoString : DEFAULT_INFO_STRING);
31
+ return await crypto.subtle.deriveKey({
32
+ name: "HKDF",
33
+ hash: "SHA-256",
34
+ salt,
35
+ info
36
+ }, ikm, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"]);
37
+ };
38
+ // src/crypto/aes_gcm/decryptBytesWithAesGcmKey.ts
39
+ var decryptBytesWithAesGcmKey = async ({
40
+ aesGcmKey,
41
+ dataToDecrypt
42
+ }) => {
43
+ const decryptedData = await crypto.subtle.decrypt({ name: "AES-GCM", iv: new Uint8Array(dataToDecrypt.nonce) }, aesGcmKey, new Uint8Array(dataToDecrypt.ciphertext));
44
+ return new Uint8Array(decryptedData);
45
+ };
46
+ // src/crypto/aes_gcm/decryptTextDataWithAesGcmKey.ts
47
+ import { base64 } from "@scure/base";
48
+ var decryptTextDataWithAesGcmKey = async ({
49
+ aesGcmKey,
50
+ dataToDecrypt
51
+ }) => {
52
+ const decryptedData = await crypto.subtle.decrypt({
53
+ name: "AES-GCM",
54
+ iv: new Uint8Array(base64.decode(dataToDecrypt.nonce))
55
+ }, aesGcmKey, new Uint8Array(base64.decode(dataToDecrypt.ciphertext)));
56
+ return new TextDecoder().decode(decryptedData);
57
+ };
58
+ // src/crypto/aes_gcm/encryptBytesWithAesGcmKey.ts
59
+ var encryptBytesWithAesGcmKey = async ({
60
+ aesGcmKey,
61
+ dataToEncrypt
62
+ }) => {
63
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
64
+ const encryptedData = await crypto.subtle.encrypt({ name: "AES-GCM", iv: nonce }, aesGcmKey, new Uint8Array(dataToEncrypt));
65
+ return { nonce, ciphertext: new Uint8Array(encryptedData) };
66
+ };
67
+ // src/crypto/aes_gcm/encryptTextDataWithAesGcmKey.ts
68
+ import { base64 as base642 } from "@scure/base";
69
+ var encryptTextDataWithAesGcmKey = async ({
70
+ aesGcmKey,
71
+ dataToEncrypt
72
+ }) => {
73
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
74
+ const encryptedData = await crypto.subtle.encrypt({
75
+ name: "AES-GCM",
76
+ iv: nonce
77
+ }, aesGcmKey, new TextEncoder().encode(dataToEncrypt));
78
+ return {
79
+ nonce: base642.encode(nonce),
80
+ ciphertext: base642.encode(new Uint8Array(encryptedData))
81
+ };
82
+ };
83
+ // src/crypto/ed25519/signTextDataWithKeyEd25519.ts
84
+ var signTextDataWithKeyEd25519 = async (data, cryptoKey) => {
85
+ const dataBuffer = new TextEncoder().encode(data);
86
+ const signature = await crypto.subtle.sign({
87
+ name: "ED25519"
88
+ }, cryptoKey, dataBuffer);
89
+ return new Uint8Array(signature);
90
+ };
91
+
92
+ // src/crypto/ed25519/signCombinedTextDataWithKeyEd25519.ts
93
+ var DEFAULT_COMBINED_TEXT_DATA_SEPARATOR = "::";
94
+ var signCombinedTextDataWithKeyEd25519 = async (data, cryptoKey, separator = DEFAULT_COMBINED_TEXT_DATA_SEPARATOR) => {
95
+ return await signTextDataWithKeyEd25519(data.join(separator), cryptoKey);
96
+ };
97
+
98
+ // src/crypto/client_key_link/buildVerifyKeyBoundInfoString.ts
99
+ var buildVerifyKeyBoundInfoString = ({
100
+ infoString,
101
+ verifyPublicKeys
102
+ }) => {
103
+ const sortedKeys = [...verifyPublicKeys].sort();
104
+ return [...infoString != null ? [infoString] : [], ...sortedKeys].join(DEFAULT_COMBINED_TEXT_DATA_SEPARATOR);
105
+ };
106
+ // src/crypto/client_key_link/ClientCryptoKeyLink.ts
107
+ import { base64 as base649 } from "@scure/base";
7
108
 
8
109
  // src/storage_adapter/typed_storage/createTypedStorage.ts
9
110
  function createTypedStorage({
@@ -40,6 +141,694 @@ function createTypedStorage({
40
141
  };
41
142
  }
42
143
 
144
+ // src/crypto/ed25519/generateEd25519KeyPair.ts
145
+ var generateEd25519KeyPair = async () => {
146
+ const keyPair = await crypto.subtle.generateKey({ name: "Ed25519" }, true, [
147
+ "sign",
148
+ "verify"
149
+ ]);
150
+ return keyPair;
151
+ };
152
+
153
+ // src/crypto/ed25519/importEd25519Key.ts
154
+ import { base64 as base644 } from "@scure/base";
155
+
156
+ // src/core/createDataStringConverter_stringToObject.ts
157
+ var createDataStringConverter_stringToObject = ({
158
+ transformJsonForFormats = [],
159
+ transformJson = false
160
+ } = {}) => (inputDataString) => {
161
+ const [type, format, dataString] = inputDataString.split("::");
162
+ let parsedData = dataString;
163
+ if (transformJson || transformJsonForFormats.includes(format)) {
164
+ try {
165
+ parsedData = JSON.parse(dataString);
166
+ } catch (error) {
167
+ const err = new Error(`Failed to parse type and format data string. Given input: "${inputDataString}", expected JSON parsable "data" value in the format "${type}::${format}::data" ${error instanceof Error ? error.message : String(error)}`);
168
+ err.cause = error;
169
+ throw err;
170
+ }
171
+ }
172
+ return {
173
+ formattedString: inputDataString,
174
+ type,
175
+ format,
176
+ data: parsedData
177
+ };
178
+ };
179
+
180
+ // src/crypto/crypto.schema.ts
181
+ import * as v2 from "valibot";
182
+
183
+ // src/core/core_valibot_schemas.ts
184
+ import * as v from "valibot";
185
+ var vBase64 = v.pipe(v.string(), v.base64());
186
+ var vCreateSchema_TypeAndFormatPrefixedDataString = ({
187
+ type,
188
+ format,
189
+ typeKind,
190
+ formatKind
191
+ }) => {
192
+ const _typeKind = typeKind ?? "data_type";
193
+ const _formatKind = formatKind ?? "data_format";
194
+ return v.pipe(v.custom((input) => {
195
+ if (typeof input !== "string")
196
+ return false;
197
+ const [typePart, formatPart, dataPart] = input.split("::");
198
+ return typePart === type && formatPart === format && typeof dataPart === "string";
199
+ }, `Invalid format, expected '<${_typeKind}>::<${_formatKind}>::<value>' where "${_typeKind}" is "${type}", "${_formatKind}" is "${format}", and "value" is a string in the specified format`));
200
+ };
201
+
202
+ // src/crypto/crypto.schema.ts
203
+ var ECryptoKeyAlgo;
204
+ ((ECryptoKeyAlgo2) => {
205
+ ECryptoKeyAlgo2["ed25519"] = "ed25519";
206
+ ECryptoKeyAlgo2["x25519"] = "x25519";
207
+ })(ECryptoKeyAlgo ||= {});
208
+ var ECryptoKeyFormat;
209
+ ((ECryptoKeyFormat2) => {
210
+ ECryptoKeyFormat2["raw_base64"] = "raw_base64";
211
+ ECryptoKeyFormat2["jwk"] = "jwk";
212
+ })(ECryptoKeyFormat ||= {});
213
+ var vSerializedCryptoKeyDataEd25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString({
214
+ format: "raw_base64" /* raw_base64 */,
215
+ type: "ed25519" /* ed25519 */,
216
+ typeKind: "algo"
217
+ });
218
+ var vSerializedCryptoKeyDataEd25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString({
219
+ format: "jwk" /* jwk */,
220
+ type: "ed25519" /* ed25519 */,
221
+ typeKind: "algo",
222
+ transformJson: true
223
+ });
224
+ var vSerializedCryptoKeyDataX25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString({
225
+ format: "raw_base64" /* raw_base64 */,
226
+ type: "x25519" /* x25519 */,
227
+ typeKind: "algo"
228
+ });
229
+ var vSerializedCryptoKeyDataX25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString({
230
+ format: "jwk" /* jwk */,
231
+ type: "x25519" /* x25519 */,
232
+ typeKind: "algo",
233
+ transformJson: true
234
+ });
235
+ var vCryptoKeyPairDataX25519 = v2.object({
236
+ publicKey: vSerializedCryptoKeyDataX25519_Raw,
237
+ privateKey: vSerializedCryptoKeyDataX25519_Jwk
238
+ });
239
+ var vCryptoKeyPairDataEd25519 = v2.object({
240
+ publicKey: vSerializedCryptoKeyDataEd25519_Raw,
241
+ privateKey: vSerializedCryptoKeyDataEd25519_Jwk
242
+ });
243
+ var vVerifyChallengeWithSignature_Input = v2.object({
244
+ challenge: v2.string(),
245
+ signatureBase64: vBase64
246
+ });
247
+ var vVerifyChallengeWithSignature_WithThrow_Input = v2.intersect([
248
+ vVerifyChallengeWithSignature_Input,
249
+ v2.object({
250
+ throwOnInvalid: v2.optional(v2.boolean())
251
+ })
252
+ ]);
253
+ var vEncryptedAesGcmPayload = v2.object({
254
+ nonce: vBase64,
255
+ ciphertext: vBase64
256
+ });
257
+
258
+ // src/crypto/crypto.converters.ts
259
+ var convertEd25519RawDataStringToObject = createDataStringConverter_stringToObject();
260
+ var convertEd25519JwkDataStringToObject = createDataStringConverter_stringToObject({ transformJson: true });
261
+ var convertEd25519FormattedStringToObject = createDataStringConverter_stringToObject({
262
+ transformJsonForFormats: ["jwk" /* jwk */]
263
+ });
264
+ var convertEd25519RawDataStringToSerializedKeyData = (input) => {
265
+ const transformed = convertEd25519RawDataStringToObject(input);
266
+ return {
267
+ prefixed: input,
268
+ transformed
269
+ };
270
+ };
271
+ var convertEd25519JwkDataStringToSerializedKeyData = (input) => {
272
+ const transformed = convertEd25519JwkDataStringToObject(input);
273
+ return {
274
+ prefixed: input,
275
+ transformed
276
+ };
277
+ };
278
+ var convertEd25519FormattedStringToSerializedKeyData = (input) => {
279
+ return convertEd25519FormattedStringToObject(input);
280
+ };
281
+ var convertX25519RawDataStringToObject = createDataStringConverter_stringToObject();
282
+ var convertX25519JwkDataStringToObject = createDataStringConverter_stringToObject({ transformJson: true });
283
+ var convertX25519FormattedStringToObject = createDataStringConverter_stringToObject({
284
+ transformJsonForFormats: ["jwk" /* jwk */]
285
+ });
286
+ var convertX25519RawDataStringToSerializedKeyData = (input) => {
287
+ const transformed = convertX25519RawDataStringToObject(input);
288
+ return {
289
+ prefixed: input,
290
+ transformed
291
+ };
292
+ };
293
+ var convertX25519JwkDataStringToSerializedKeyData = (input) => {
294
+ const transformed = convertX25519JwkDataStringToObject(input);
295
+ return {
296
+ prefixed: input,
297
+ transformed
298
+ };
299
+ };
300
+ var convertX25519FormattedStringToSerializedKeyData = (input) => {
301
+ return convertX25519FormattedStringToObject(input);
302
+ };
303
+
304
+ // src/crypto/ed25519/importEd25519Key.ts
305
+ var fromBase64 = async (dataBase64, keyUsage, extractable) => {
306
+ const keyBuffer = Uint8Array.from(base644.decode(dataBase64));
307
+ return await crypto.subtle.importKey("raw", keyBuffer, { name: "Ed25519" }, extractable, keyUsage);
308
+ };
309
+ var fromJwk = async (jwk, keyUsage, extractable = true) => {
310
+ return await crypto.subtle.importKey("jwk", jwk, { name: "Ed25519" }, extractable, keyUsage);
311
+ };
312
+ var fromSerializedObject = async (serialized, keyUsage, extractable = true) => {
313
+ if (serialized.format === "jwk" /* jwk */) {
314
+ return await fromJwk(serialized.data, keyUsage, extractable);
315
+ }
316
+ return await fromBase64(serialized.data, keyUsage, extractable);
317
+ };
318
+ var fromFormattedString = async (dataString, keyUsage, extractable = true) => {
319
+ const transformed = convertEd25519FormattedStringToSerializedKeyData(dataString);
320
+ return await fromSerializedObject(transformed, keyUsage, extractable);
321
+ };
322
+ var extractableOrNonExtractable = (keyUsage, func) => ({
323
+ extractable: (input) => func(input, keyUsage, true),
324
+ nonExtractable: (input) => func(input, keyUsage, false)
325
+ });
326
+ var importEd25519Key = {
327
+ private: {
328
+ fromFormattedString: extractableOrNonExtractable(["sign"], fromFormattedString),
329
+ fromSerializedObject: extractableOrNonExtractable(["sign"], fromSerializedObject),
330
+ fromJwk: extractableOrNonExtractable(["sign"], fromJwk)
331
+ },
332
+ public: {
333
+ fromBase64: extractableOrNonExtractable(["verify"], fromBase64),
334
+ fromFormattedString: extractableOrNonExtractable(["verify"], fromFormattedString),
335
+ fromSerializedObject: extractableOrNonExtractable(["verify"], fromSerializedObject),
336
+ fromJwk: extractableOrNonExtractable(["verify"], fromJwk)
337
+ }
338
+ };
339
+
340
+ // src/crypto/ed25519/serializeEd25519Key_Jwk.ts
341
+ var serializeEd25519Key_Jwk = async (key) => {
342
+ const keyJwk = await crypto.subtle.exportKey("jwk", key);
343
+ const prefixed = `${"ed25519" /* ed25519 */}::${"jwk" /* jwk */}::${JSON.stringify(keyJwk)}`;
344
+ const transformed = {
345
+ formattedString: prefixed,
346
+ type: "ed25519" /* ed25519 */,
347
+ data: keyJwk,
348
+ format: "jwk" /* jwk */
349
+ };
350
+ return { transformed, prefixed };
351
+ };
352
+
353
+ // src/crypto/ed25519/serializeEd25519Key_Raw.ts
354
+ import { base64 as base645 } from "@scure/base";
355
+ var serializeEd25519Key_Raw = async (publicKey) => {
356
+ const publicKeyBuffer = await crypto.subtle.exportKey("raw", publicKey);
357
+ const publicKeyBase64 = base645.encode(new Uint8Array(publicKeyBuffer));
358
+ const prefixed = `${"ed25519" /* ed25519 */}::${"raw_base64" /* raw_base64 */}::${publicKeyBase64}`;
359
+ const transformed = {
360
+ formattedString: prefixed,
361
+ type: "ed25519" /* ed25519 */,
362
+ data: publicKeyBase64,
363
+ format: "raw_base64" /* raw_base64 */
364
+ };
365
+ return { transformed, prefixed };
366
+ };
367
+
368
+ // src/crypto/ed25519/verifyWithKeyEd25519.ts
369
+ import { base64 as base646 } from "@scure/base";
370
+ var verifyWithKeyEd25519 = async ({
371
+ challenge,
372
+ signatureBase64,
373
+ publicKey
374
+ }) => {
375
+ const signatureBuffer = Uint8Array.from(base646.decode(signatureBase64));
376
+ const challengeBuffer = new TextEncoder().encode(challenge);
377
+ return await crypto.subtle.verify({
378
+ name: "ED25519"
379
+ }, publicKey, signatureBuffer, challengeBuffer);
380
+ };
381
+
382
+ // src/crypto/x25519/generateX25519KeyPair.ts
383
+ var generateX25519KeyPair = async () => {
384
+ const keyPair = await crypto.subtle.generateKey({ name: "X25519" }, true, [
385
+ "deriveKey",
386
+ "deriveBits"
387
+ ]);
388
+ return keyPair;
389
+ };
390
+
391
+ // src/crypto/x25519/importX25519Key.ts
392
+ import { base64 as base647 } from "@scure/base";
393
+ var fromBase642 = async (dataBase64, keyUsage, extractable) => {
394
+ const keyBuffer = Uint8Array.from(base647.decode(dataBase64));
395
+ return await crypto.subtle.importKey("raw", keyBuffer, { name: "X25519" }, extractable, keyUsage);
396
+ };
397
+ var fromJwk2 = async (jwk, keyUsage, extractable = true) => {
398
+ return await crypto.subtle.importKey("jwk", jwk, { name: "X25519" }, extractable, keyUsage);
399
+ };
400
+ var fromSerializedObject2 = async (serialized, keyUsage, extractable = true) => {
401
+ if (serialized.format === "jwk" /* jwk */) {
402
+ return await fromJwk2(serialized.data, keyUsage, extractable);
403
+ }
404
+ return await fromBase642(serialized.data, keyUsage, extractable);
405
+ };
406
+ var fromFormattedString2 = async (dataString, keyUsage, extractable = true) => {
407
+ const transformed = convertX25519FormattedStringToSerializedKeyData(dataString);
408
+ return await fromSerializedObject2(transformed, keyUsage, extractable);
409
+ };
410
+ var extractableOrNonExtractable2 = (keyUsage, func) => ({
411
+ extractable: (input) => func(input, keyUsage, true),
412
+ nonExtractable: (input) => func(input, keyUsage, false)
413
+ });
414
+ var importX25519Key = {
415
+ private: {
416
+ fromFormattedString: extractableOrNonExtractable2(["deriveKey", "deriveBits"], fromFormattedString2),
417
+ fromSerializedObject: extractableOrNonExtractable2(["deriveKey", "deriveBits"], fromSerializedObject2),
418
+ fromJwk: extractableOrNonExtractable2(["deriveKey", "deriveBits"], fromJwk2)
419
+ },
420
+ public: {
421
+ fromBase64: extractableOrNonExtractable2([], fromBase642),
422
+ fromFormattedString: extractableOrNonExtractable2([], fromFormattedString2),
423
+ fromSerializedObject: extractableOrNonExtractable2([], fromSerializedObject2),
424
+ fromJwk: extractableOrNonExtractable2([], fromJwk2)
425
+ }
426
+ };
427
+
428
+ // src/crypto/x25519/serializeX25519Key_Jwk.ts
429
+ var serializeX25519Key_Jwk = async (key) => {
430
+ const publicKeyJwk = await crypto.subtle.exportKey("jwk", key);
431
+ const prefixed = `${"x25519" /* x25519 */}::${"jwk" /* jwk */}::${JSON.stringify(publicKeyJwk)}`;
432
+ const transformed = {
433
+ formattedString: prefixed,
434
+ type: "x25519" /* x25519 */,
435
+ data: publicKeyJwk,
436
+ format: "jwk" /* jwk */
437
+ };
438
+ return { transformed, prefixed };
439
+ };
440
+
441
+ // src/crypto/x25519/serializeX25519Key_Raw.ts
442
+ import { base64 as base648 } from "@scure/base";
443
+ var serializeX25519Key_Raw = async (key) => {
444
+ const publicKeyBuffer = await crypto.subtle.exportKey("raw", key);
445
+ const publicKeyBase64 = base648.encode(new Uint8Array(publicKeyBuffer));
446
+ const prefixed = `${"x25519" /* x25519 */}::${"raw_base64" /* raw_base64 */}::${publicKeyBase64}`;
447
+ const transformed = {
448
+ formattedString: prefixed,
449
+ type: "x25519" /* x25519 */,
450
+ data: publicKeyBase64,
451
+ format: "raw_base64" /* raw_base64 */
452
+ };
453
+ return { transformed, prefixed };
454
+ };
455
+
456
+ // src/crypto/client_key_link/ClientCryptoKeyLink.ts
457
+ class ClientCryptoKeyLink {
458
+ localExchangeKeyPair;
459
+ localVerifyKeyPair;
460
+ linkedClientKeys = new Map;
461
+ storage;
462
+ initialized = false;
463
+ initializePromise;
464
+ localExchangeKeyPairPromise;
465
+ localVerifyKeyPairPromise;
466
+ constructor({ storageAdapter } = {}) {
467
+ if (storageAdapter != null) {
468
+ this.storage = createTypedStorage({ storageAdapter });
469
+ }
470
+ }
471
+ async initialize() {
472
+ if (this.initialized) {
473
+ return;
474
+ }
475
+ this.initializePromise ??= this.runInitialize();
476
+ try {
477
+ await this.initializePromise;
478
+ } finally {
479
+ this.initializePromise = undefined;
480
+ }
481
+ }
482
+ async runInitialize() {
483
+ await this.loadStoredLocalKeys();
484
+ await this.loadLinkedClients();
485
+ this.initialized = true;
486
+ }
487
+ async loadStoredLocalKeys() {
488
+ const storedExchange = await this.storage?.getJson("localExchangeKeyPair");
489
+ if (storedExchange != null) {
490
+ this.localExchangeKeyPair = {
491
+ privateKey: await importX25519Key.private.fromFormattedString.extractable(storedExchange.privateKey),
492
+ publicKey: await importX25519Key.public.fromFormattedString.extractable(storedExchange.publicKey)
493
+ };
494
+ }
495
+ const storedVerify = await this.storage?.getJson("localVerifyKeyPair");
496
+ if (storedVerify != null) {
497
+ this.localVerifyKeyPair = {
498
+ privateKey: await importEd25519Key.private.fromFormattedString.extractable(storedVerify.privateKey),
499
+ publicKey: await importEd25519Key.public.fromFormattedString.extractable(storedVerify.publicKey)
500
+ };
501
+ }
502
+ }
503
+ async ensureLocalExchangeKeyPair() {
504
+ if (this.localExchangeKeyPair != null) {
505
+ return this.localExchangeKeyPair;
506
+ }
507
+ this.localExchangeKeyPairPromise ??= (async () => {
508
+ const keyPair = await generateX25519KeyPair();
509
+ this.localExchangeKeyPair = keyPair;
510
+ if (this.storage != null) {
511
+ await this.storage.setJson("localExchangeKeyPair", await this.serializeExchangeKeyPair(keyPair));
512
+ }
513
+ return keyPair;
514
+ })();
515
+ try {
516
+ return await this.localExchangeKeyPairPromise;
517
+ } finally {
518
+ this.localExchangeKeyPairPromise = undefined;
519
+ }
520
+ }
521
+ async ensureLocalVerifyKeyPair() {
522
+ if (this.localVerifyKeyPair != null) {
523
+ return this.localVerifyKeyPair;
524
+ }
525
+ this.localVerifyKeyPairPromise ??= (async () => {
526
+ const keyPair = await generateEd25519KeyPair();
527
+ this.localVerifyKeyPair = keyPair;
528
+ if (this.storage != null) {
529
+ await this.storage.setJson("localVerifyKeyPair", await this.serializeVerifyKeyPair(keyPair));
530
+ }
531
+ return keyPair;
532
+ })();
533
+ try {
534
+ return await this.localVerifyKeyPairPromise;
535
+ } finally {
536
+ this.localVerifyKeyPairPromise = undefined;
537
+ }
538
+ }
539
+ async loadLinkedClients() {
540
+ const storedLinkedClients = await this.storage?.getJson("linkedClientPublicKeys");
541
+ if (storedLinkedClients == null) {
542
+ return;
543
+ }
544
+ for (const [linkedClientId, publicKeys] of Object.entries(storedLinkedClients)) {
545
+ await this.linkClient({
546
+ linkedClientId,
547
+ verifyPublicKey: publicKeys.verifyPublicKey,
548
+ exchangePublicKey: publicKeys.exchangePublicKey,
549
+ saltString: publicKeys.saltString,
550
+ infoString: publicKeys.infoString,
551
+ bindVerifyKeysIntoDerivation: publicKeys.bindVerifyKeysIntoDerivation
552
+ });
553
+ }
554
+ }
555
+ async serializeExchangeKeyPair(keyPair) {
556
+ return {
557
+ publicKey: (await serializeX25519Key_Raw(keyPair.publicKey)).prefixed,
558
+ privateKey: (await serializeX25519Key_Jwk(keyPair.privateKey)).prefixed
559
+ };
560
+ }
561
+ async serializeVerifyKeyPair(keyPair) {
562
+ return {
563
+ publicKey: (await serializeEd25519Key_Raw(keyPair.publicKey)).prefixed,
564
+ privateKey: (await serializeEd25519Key_Jwk(keyPair.privateKey)).prefixed
565
+ };
566
+ }
567
+ async getLocalPublicKeys() {
568
+ return {
569
+ verifyPublicKey: await this.getLocalVerifyPublicKey(),
570
+ exchangePublicKey: await this.getLocalExchangePublicKey()
571
+ };
572
+ }
573
+ async getLocalExchangePublicKey() {
574
+ const exchangeKeyPair = await this.ensureLocalExchangeKeyPair();
575
+ return (await serializeX25519Key_Raw(exchangeKeyPair.publicKey)).prefixed;
576
+ }
577
+ async getLocalVerifyPublicKey() {
578
+ const verifyKeyPair = await this.ensureLocalVerifyKeyPair();
579
+ return (await serializeEd25519Key_Raw(verifyKeyPair.publicKey)).prefixed;
580
+ }
581
+ async linkClient({
582
+ linkedClientId,
583
+ verifyPublicKey,
584
+ exchangePublicKey,
585
+ saltString,
586
+ infoString,
587
+ bindVerifyKeysIntoDerivation
588
+ }) {
589
+ const existing = this.linkedClientKeys.get(linkedClientId);
590
+ const verify = verifyPublicKey != null ? {
591
+ publicKey: await importEd25519Key.public.fromFormattedString.extractable(verifyPublicKey),
592
+ publicKeySerialized: verifyPublicKey
593
+ } : existing?.verify;
594
+ const verifyKeyChanged = verifyPublicKey != null && verifyPublicKey !== existing?.verify?.publicKeySerialized;
595
+ let exchange = existing?.exchange;
596
+ const exchangeParamsProvided = exchangePublicKey != null || saltString !== undefined || infoString !== undefined || bindVerifyKeysIntoDerivation !== undefined;
597
+ if (exchangeParamsProvided) {
598
+ const nextPublicKeySerialized = exchangePublicKey ?? existing?.exchange?.publicKeySerialized;
599
+ if (nextPublicKeySerialized == null) {
600
+ throw new Error(`ClientCryptoKeyLink: Cannot set salt/info for ${linkedClientId} without an exchange public key`);
601
+ }
602
+ const nextSalt = saltString !== undefined ? saltString : existing?.exchange?.saltString;
603
+ const nextInfo = infoString !== undefined ? infoString : existing?.exchange?.infoString;
604
+ const nextBind = bindVerifyKeysIntoDerivation !== undefined ? bindVerifyKeysIntoDerivation : existing?.exchange?.bindVerifyKeysIntoDerivation;
605
+ const publicKey = exchangePublicKey != null ? await importX25519Key.public.fromFormattedString.extractable(exchangePublicKey) : existing.exchange.publicKey;
606
+ const unchanged = nextPublicKeySerialized === existing?.exchange?.publicKeySerialized && nextSalt === existing?.exchange?.saltString && nextInfo === existing?.exchange?.infoString && nextBind === existing?.exchange?.bindVerifyKeysIntoDerivation && !(nextBind === true && verifyKeyChanged);
607
+ exchange = {
608
+ publicKey,
609
+ publicKeySerialized: nextPublicKeySerialized,
610
+ saltString: nextSalt,
611
+ infoString: nextInfo,
612
+ bindVerifyKeysIntoDerivation: nextBind,
613
+ sharedEncryptKey: unchanged ? existing?.exchange?.sharedEncryptKey : undefined
614
+ };
615
+ } else if (exchange?.bindVerifyKeysIntoDerivation === true && verifyKeyChanged && exchange.sharedEncryptKey != null) {
616
+ exchange = { ...exchange, sharedEncryptKey: undefined };
617
+ }
618
+ this.linkedClientKeys.set(linkedClientId, { verify, exchange });
619
+ }
620
+ async linkClientAndStore(input) {
621
+ await this.linkClient(input);
622
+ if (this.storage == null) {
623
+ return;
624
+ }
625
+ const {
626
+ linkedClientId,
627
+ verifyPublicKey,
628
+ exchangePublicKey,
629
+ saltString,
630
+ infoString,
631
+ bindVerifyKeysIntoDerivation
632
+ } = input;
633
+ await this.storage.updateJsonWithDef("linkedClientPublicKeys", {}, (current) => ({
634
+ ...current,
635
+ [linkedClientId]: {
636
+ ...current[linkedClientId],
637
+ ...verifyPublicKey != null ? { verifyPublicKey } : {},
638
+ ...exchangePublicKey != null ? { exchangePublicKey } : {},
639
+ ...saltString !== undefined ? { saltString } : {},
640
+ ...infoString !== undefined ? { infoString } : {},
641
+ ...bindVerifyKeysIntoDerivation !== undefined ? { bindVerifyKeysIntoDerivation } : {}
642
+ }
643
+ }));
644
+ }
645
+ hasLinkedClient(linkedClientId) {
646
+ return this.linkedClientKeys.has(linkedClientId);
647
+ }
648
+ getLinkedClientPublicKeys(linkedClientId) {
649
+ const linkedClient = this.linkedClientKeys.get(linkedClientId);
650
+ if (linkedClient == null) {
651
+ return;
652
+ }
653
+ return {
654
+ verifyPublicKey: linkedClient.verify?.publicKeySerialized,
655
+ exchangePublicKey: linkedClient.exchange?.publicKeySerialized
656
+ };
657
+ }
658
+ async unlinkClient(linkedClientId) {
659
+ this.linkedClientKeys.delete(linkedClientId);
660
+ if (this.storage != null) {
661
+ await this.storage.updateJson("linkedClientPublicKeys", (current) => {
662
+ if (current == null) {
663
+ return {};
664
+ }
665
+ const { [linkedClientId]: _removed, ...rest } = current;
666
+ return rest;
667
+ });
668
+ }
669
+ }
670
+ async unlinkAllClients() {
671
+ this.linkedClientKeys.clear();
672
+ if (this.storage != null) {
673
+ await this.storage.setJson("linkedClientPublicKeys", {});
674
+ }
675
+ }
676
+ async reset() {
677
+ this.linkedClientKeys.clear();
678
+ this.localExchangeKeyPair = undefined;
679
+ this.localVerifyKeyPair = undefined;
680
+ this.initialized = false;
681
+ if (this.storage != null) {
682
+ await this.storage.removeItem("linkedClientPublicKeys");
683
+ await this.storage.removeItem("localExchangeKeyPair");
684
+ await this.storage.removeItem("localVerifyKeyPair");
685
+ }
686
+ }
687
+ getLinkedClient(linkedClientId) {
688
+ const linkedClient = this.linkedClientKeys.get(linkedClientId);
689
+ if (linkedClient == null) {
690
+ throw new Error(`ClientCryptoKeyLink: No linked client for ${linkedClientId}`);
691
+ }
692
+ return linkedClient;
693
+ }
694
+ async getAesGcmKeyForLinkedClient(externalClientSourceId) {
695
+ const linkedClient = this.getLinkedClient(externalClientSourceId);
696
+ if (linkedClient.exchange?.sharedEncryptKey != null) {
697
+ return linkedClient.exchange.sharedEncryptKey;
698
+ }
699
+ if (linkedClient.exchange?.publicKey == null) {
700
+ throw new Error(`ClientCryptoKeyLink: No public exchange key set for ${externalClientSourceId}`);
701
+ }
702
+ const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();
703
+ let infoString = linkedClient.exchange.infoString;
704
+ if (linkedClient.exchange.bindVerifyKeysIntoDerivation === true) {
705
+ const linkedVerifyPublicKey = linkedClient.verify?.publicKeySerialized;
706
+ if (linkedVerifyPublicKey == null) {
707
+ throw new Error(`ClientCryptoKeyLink: Link for ${externalClientSourceId} binds verify keys into the derivation, but no verify public key is set`);
708
+ }
709
+ infoString = buildVerifyKeyBoundInfoString({
710
+ infoString: linkedClient.exchange.infoString,
711
+ verifyPublicKeys: [await this.getLocalVerifyPublicKey(), linkedVerifyPublicKey]
712
+ });
713
+ }
714
+ const sharedEncryptKey = await createAesGcmKeyFromX25519Keys({
715
+ internalX25519PrivateKey: localExchangeKeyPair.privateKey,
716
+ externalX25519PublicKey: linkedClient.exchange.publicKey,
717
+ saltString: linkedClient.exchange.saltString,
718
+ infoString
719
+ });
720
+ this.linkedClientKeys.set(externalClientSourceId, {
721
+ ...linkedClient,
722
+ exchange: {
723
+ ...linkedClient.exchange,
724
+ sharedEncryptKey
725
+ }
726
+ });
727
+ return sharedEncryptKey;
728
+ }
729
+ async encryptDataForLinkedClient({
730
+ dataToEncrypt,
731
+ linkedClientId
732
+ }) {
733
+ const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);
734
+ return await encryptTextDataWithAesGcmKey({
735
+ dataToEncrypt,
736
+ aesGcmKey: key
737
+ });
738
+ }
739
+ async decryptDataFromLinkedClient({
740
+ dataToDecrypt,
741
+ linkedClientId
742
+ }) {
743
+ const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);
744
+ return await decryptTextDataWithAesGcmKey({
745
+ dataToDecrypt,
746
+ aesGcmKey: key
747
+ });
748
+ }
749
+ async encryptBytesForLinkedClient({
750
+ dataToEncrypt,
751
+ linkedClientId
752
+ }) {
753
+ const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);
754
+ return await encryptBytesWithAesGcmKey({
755
+ dataToEncrypt,
756
+ aesGcmKey: key
757
+ });
758
+ }
759
+ async decryptBytesFromLinkedClient({
760
+ dataToDecrypt,
761
+ linkedClientId
762
+ }) {
763
+ const key = await this.getAesGcmKeyForLinkedClient(linkedClientId);
764
+ return await decryptBytesWithAesGcmKey({
765
+ dataToDecrypt,
766
+ aesGcmKey: key
767
+ });
768
+ }
769
+ async signAndEncryptDataForLinkedClient({
770
+ dataToEncrypt,
771
+ linkedClientId
772
+ }) {
773
+ const { signatureBase64 } = await this.signChallenge([dataToEncrypt]);
774
+ const encryptedData = await this.encryptDataForLinkedClient({
775
+ dataToEncrypt,
776
+ linkedClientId
777
+ });
778
+ return {
779
+ encryptedData,
780
+ signatureBase64
781
+ };
782
+ }
783
+ async decryptAndVerifyDataFromLinkedClient({
784
+ dataToDecrypt,
785
+ linkedClientId,
786
+ signatureBase64
787
+ }) {
788
+ const data = await this.decryptDataFromLinkedClient({
789
+ dataToDecrypt,
790
+ linkedClientId
791
+ });
792
+ const isValid = await this.verifyChallengeFromLinkedClient({
793
+ linkedClientId,
794
+ challenge: data,
795
+ signatureBase64
796
+ });
797
+ return { data, isValid };
798
+ }
799
+ async signChallenge(challenge) {
800
+ if (challenge.length === 0) {
801
+ throw new Error("Challenge must contain at least one string");
802
+ }
803
+ const localVerifyKeyPair = await this.ensureLocalVerifyKeyPair();
804
+ const signature = challenge.length > 1 ? await signCombinedTextDataWithKeyEd25519(challenge, localVerifyKeyPair.privateKey) : await signTextDataWithKeyEd25519(challenge[0], localVerifyKeyPair.privateKey);
805
+ return {
806
+ signatureBase64: base649.encode(signature)
807
+ };
808
+ }
809
+ async verifyChallengeFromLinkedClient({
810
+ linkedClientId,
811
+ challenge,
812
+ signatureBase64
813
+ }) {
814
+ const linkedClient = this.getLinkedClient(linkedClientId);
815
+ if (linkedClient.verify?.publicKey == null) {
816
+ throw new Error(`ClientCryptoKeyLink: No verify public key set for ${linkedClientId}`);
817
+ }
818
+ return await verifyWithKeyEd25519({
819
+ challenge,
820
+ signatureBase64,
821
+ publicKey: linkedClient.verify.publicKey
822
+ });
823
+ }
824
+ }
825
+ // src/storage_adapter/storage_adapter.types.ts
826
+ var EStorageAdapterType;
827
+ ((EStorageAdapterType2) => {
828
+ EStorageAdapterType2["string"] = "string";
829
+ EStorageAdapterType2["json"] = "json";
830
+ })(EStorageAdapterType ||= {});
831
+
43
832
  // src/storage_adapter/StorageAdapter.ts
44
833
  class StorageAdapter {
45
834
  implementation;
@@ -268,6 +1057,30 @@ function createTypedMemoryStorage_json(options) {
268
1057
  });
269
1058
  }
270
1059
  export {
1060
+ verifyWithKeyEd25519,
1061
+ vVerifyChallengeWithSignature_WithThrow_Input,
1062
+ vVerifyChallengeWithSignature_Input,
1063
+ vSerializedCryptoKeyDataX25519_Raw,
1064
+ vSerializedCryptoKeyDataX25519_Jwk,
1065
+ vSerializedCryptoKeyDataEd25519_Raw,
1066
+ vSerializedCryptoKeyDataEd25519_Jwk,
1067
+ vEncryptedAesGcmPayload,
1068
+ vCryptoKeyPairDataX25519,
1069
+ vCryptoKeyPairDataEd25519,
1070
+ signTextDataWithKeyEd25519,
1071
+ signCombinedTextDataWithKeyEd25519,
1072
+ serializeX25519Key_Raw,
1073
+ serializeX25519Key_Jwk,
1074
+ serializeEd25519Key_Raw,
1075
+ serializeEd25519Key_Jwk,
1076
+ importX25519Key,
1077
+ importEd25519Key,
1078
+ generateX25519KeyPair,
1079
+ generateEd25519KeyPair,
1080
+ encryptTextDataWithAesGcmKey,
1081
+ encryptBytesWithAesGcmKey,
1082
+ decryptTextDataWithAesGcmKey,
1083
+ decryptBytesWithAesGcmKey,
271
1084
  createWebSessionStorageMethods,
272
1085
  createWebSessionStorageAdapter,
273
1086
  createWebLocalStorageMethods,
@@ -277,6 +1090,7 @@ export {
277
1090
  createTypedStorage,
278
1091
  createTypedMemoryStorage_string,
279
1092
  createTypedMemoryStorage_json,
1093
+ createSharedBitsFromX25519,
280
1094
  createMemoryStorageMethods_string,
281
1095
  createMemoryStorageMethods_json,
282
1096
  createMemoryStorageAdapter_string,
@@ -284,6 +1098,24 @@ export {
284
1098
  createDurableObjectTypedStorage,
285
1099
  createDurableObjectStorageMethods,
286
1100
  createDurableObjectStorageAdapter,
1101
+ createAesGcmKeyFromX25519Keys,
1102
+ convertX25519RawDataStringToSerializedKeyData,
1103
+ convertX25519RawDataStringToObject,
1104
+ convertX25519JwkDataStringToSerializedKeyData,
1105
+ convertX25519JwkDataStringToObject,
1106
+ convertX25519FormattedStringToSerializedKeyData,
1107
+ convertX25519FormattedStringToObject,
1108
+ convertEd25519RawDataStringToSerializedKeyData,
1109
+ convertEd25519RawDataStringToObject,
1110
+ convertEd25519JwkDataStringToSerializedKeyData,
1111
+ convertEd25519JwkDataStringToObject,
1112
+ convertEd25519FormattedStringToSerializedKeyData,
1113
+ convertEd25519FormattedStringToObject,
1114
+ buildVerifyKeyBoundInfoString,
287
1115
  StorageAdapter,
288
- EStorageAdapterType
1116
+ EStorageAdapterType,
1117
+ ECryptoKeyFormat,
1118
+ ECryptoKeyAlgo,
1119
+ DEFAULT_COMBINED_TEXT_DATA_SEPARATOR,
1120
+ ClientCryptoKeyLink
289
1121
  };