@nice-code/util 0.10.0 → 0.12.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.
@@ -0,0 +1,1126 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
13
+ get: ((k) => from[k]).bind(null, key),
14
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
+ });
16
+ }
17
+ return to;
18
+ };
19
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ value: mod,
21
+ enumerable: true
22
+ }) : target, mod));
23
+ //#endregion
24
+ let _scure_base = require("@scure/base");
25
+ let valibot = require("valibot");
26
+ valibot = __toESM(valibot, 1);
27
+ //#region src/data_type/string/nullEmpty.ts
28
+ const notNullEmpty = (str) => {
29
+ return str != null && str.length > 0;
30
+ };
31
+ //#endregion
32
+ //#region src/crypto/x25519/createSharedBitsFromX25519.ts
33
+ const createSharedBitsFromX25519 = async ({ privateKey, publicKey }) => {
34
+ return new Uint8Array(await crypto.subtle.deriveBits({
35
+ name: "X25519",
36
+ public: publicKey
37
+ }, privateKey, 256));
38
+ };
39
+ //#endregion
40
+ //#region src/crypto/aes_gcm/createAesGcmKeyFromX25519Keys.ts
41
+ const DEFAULT_INFO_STRING = "METEOR_BRIDGE_DEFAULT_INFO_STRING";
42
+ const createAesGcmKeyFromX25519Keys = async ({ externalX25519PublicKey, internalX25519PrivateKey, infoString, saltString }) => {
43
+ const sharedBits = await createSharedBitsFromX25519({
44
+ privateKey: internalX25519PrivateKey,
45
+ publicKey: externalX25519PublicKey
46
+ });
47
+ const ikm = await crypto.subtle.importKey("raw", new Uint8Array(sharedBits), "HKDF", false, ["deriveKey"]);
48
+ const salt = notNullEmpty(saltString) ? new TextEncoder().encode(saltString) : new Uint8Array();
49
+ const info = new TextEncoder().encode(notNullEmpty(infoString) ? infoString : DEFAULT_INFO_STRING);
50
+ return await crypto.subtle.deriveKey({
51
+ name: "HKDF",
52
+ hash: "SHA-256",
53
+ salt,
54
+ info
55
+ }, ikm, {
56
+ name: "AES-GCM",
57
+ length: 256
58
+ }, false, ["encrypt", "decrypt"]);
59
+ };
60
+ //#endregion
61
+ //#region src/crypto/aes_gcm/decryptBytesWithAesGcmKey.ts
62
+ /**
63
+ * Decrypts a raw-bytes AES-GCM payload (binary nonce + ciphertext) back to bytes. The counterpart of
64
+ * {@link decryptTextDataWithAesGcmKey}. AES-GCM verifies integrity, so a tampered ciphertext throws.
65
+ */
66
+ const decryptBytesWithAesGcmKey = async ({ aesGcmKey, dataToDecrypt }) => {
67
+ const decryptedData = await crypto.subtle.decrypt({
68
+ name: "AES-GCM",
69
+ iv: new Uint8Array(dataToDecrypt.nonce)
70
+ }, aesGcmKey, new Uint8Array(dataToDecrypt.ciphertext));
71
+ return new Uint8Array(decryptedData);
72
+ };
73
+ //#endregion
74
+ //#region src/crypto/aes_gcm/decryptTextDataWithAesGcmKey.ts
75
+ const decryptTextDataWithAesGcmKey = async ({ aesGcmKey, dataToDecrypt }) => {
76
+ const decryptedData = await crypto.subtle.decrypt({
77
+ name: "AES-GCM",
78
+ iv: new Uint8Array(_scure_base.base64.decode(dataToDecrypt.nonce))
79
+ }, aesGcmKey, new Uint8Array(_scure_base.base64.decode(dataToDecrypt.ciphertext)));
80
+ return new TextDecoder().decode(decryptedData);
81
+ };
82
+ //#endregion
83
+ //#region src/crypto/aes_gcm/encryptBytesWithAesGcmKey.ts
84
+ /**
85
+ * Encrypts raw bytes with an AES-GCM key, returning the binary nonce + ciphertext. The bytes
86
+ * counterpart of {@link encryptTextDataWithAesGcmKey} — use it for binary channels (msgpack frames)
87
+ * to avoid base64 inflation. A fresh 12-byte nonce is generated per call (never reuse a nonce).
88
+ */
89
+ const encryptBytesWithAesGcmKey = async ({ aesGcmKey, dataToEncrypt }) => {
90
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
91
+ const encryptedData = await crypto.subtle.encrypt({
92
+ name: "AES-GCM",
93
+ iv: nonce
94
+ }, aesGcmKey, new Uint8Array(dataToEncrypt));
95
+ return {
96
+ nonce,
97
+ ciphertext: new Uint8Array(encryptedData)
98
+ };
99
+ };
100
+ //#endregion
101
+ //#region src/crypto/aes_gcm/encryptTextDataWithAesGcmKey.ts
102
+ const encryptTextDataWithAesGcmKey = async ({ aesGcmKey, dataToEncrypt }) => {
103
+ const nonce = crypto.getRandomValues(new Uint8Array(12));
104
+ const encryptedData = await crypto.subtle.encrypt({
105
+ name: "AES-GCM",
106
+ iv: nonce
107
+ }, aesGcmKey, new TextEncoder().encode(dataToEncrypt));
108
+ return {
109
+ nonce: _scure_base.base64.encode(nonce),
110
+ ciphertext: _scure_base.base64.encode(new Uint8Array(encryptedData))
111
+ };
112
+ };
113
+ //#endregion
114
+ //#region src/crypto/ed25519/signTextDataWithKeyEd25519.ts
115
+ const signTextDataWithKeyEd25519 = async (data, cryptoKey) => {
116
+ const dataBuffer = new TextEncoder().encode(data);
117
+ const signature = await crypto.subtle.sign({ name: "ED25519" }, cryptoKey, dataBuffer);
118
+ return new Uint8Array(signature);
119
+ };
120
+ //#endregion
121
+ //#region src/crypto/ed25519/signCombinedTextDataWithKeyEd25519.ts
122
+ const DEFAULT_COMBINED_TEXT_DATA_SEPARATOR = "::";
123
+ const signCombinedTextDataWithKeyEd25519 = async (data, cryptoKey, separator = "::") => {
124
+ return await signTextDataWithKeyEd25519(data.join(separator), cryptoKey);
125
+ };
126
+ //#endregion
127
+ //#region src/crypto/client_key_link/buildVerifyKeyBoundInfoString.ts
128
+ /**
129
+ * The canonical HKDF `info` for a client-to-client shared key that binds both sides' verify
130
+ * public keys into the derivation.
131
+ *
132
+ * When the two keys are relayed through an intermediary, a tampered key produces mismatched AES
133
+ * keys on the two sides — the very first decryption fails, so key substitution is detected without
134
+ * any extra signature ceremony.
135
+ *
136
+ * The keys are sorted lexicographically so the result is independent of which side is "local" —
137
+ * both ends of a link compute the identical string without coordinating an order. Used internally
138
+ * by ClientCryptoKeyLink (`bindVerifyKeysIntoDerivation`); exported for code that derives the same
139
+ * key outside the link.
140
+ */
141
+ const buildVerifyKeyBoundInfoString = ({ infoString, verifyPublicKeys }) => {
142
+ const sortedKeys = [...verifyPublicKeys].sort();
143
+ return [...infoString != null ? [infoString] : [], ...sortedKeys].join("::");
144
+ };
145
+ //#endregion
146
+ //#region src/storage_adapter/typed_storage/createTypedStorage.ts
147
+ function createTypedStorage({ storageAdapter }) {
148
+ const getJson = async (key) => {
149
+ return storageAdapter.getJson(key);
150
+ };
151
+ const getJsonOrDef = async (key, defVal) => {
152
+ return await storageAdapter.getJson(key) ?? defVal;
153
+ };
154
+ const setJson = async (key, val) => {
155
+ return storageAdapter.setJson(key, val);
156
+ };
157
+ const removeItem = async (key) => {
158
+ await storageAdapter.removeItem(key);
159
+ };
160
+ const updateJson = async (key, updater) => {
161
+ await storageAdapter.updateJson(key, updater);
162
+ };
163
+ const updateJsonWithDef = async (key, defaultVal, updater) => {
164
+ await storageAdapter.updateJsonOrDef(key, defaultVal, updater);
165
+ };
166
+ return {
167
+ getJson,
168
+ getJsonOrDef,
169
+ setJson,
170
+ removeItem,
171
+ updateJson,
172
+ updateJsonWithDef,
173
+ clearAll: async () => {
174
+ await storageAdapter.clearAll();
175
+ }
176
+ };
177
+ }
178
+ //#endregion
179
+ //#region src/crypto/ed25519/generateEd25519KeyPair.ts
180
+ const generateEd25519KeyPair = async () => {
181
+ return await crypto.subtle.generateKey({ name: "Ed25519" }, true, ["sign", "verify"]);
182
+ };
183
+ //#endregion
184
+ //#region src/core/createDataStringConverter_stringToObject.ts
185
+ const createDataStringConverter_stringToObject = ({ transformJsonForFormats = [], transformJson = false } = {}) => (inputDataString) => {
186
+ const [type, format, dataString] = inputDataString.split("::");
187
+ let parsedData = dataString;
188
+ if (transformJson || transformJsonForFormats.includes(format)) try {
189
+ parsedData = JSON.parse(dataString);
190
+ } catch (error) {
191
+ const err = /* @__PURE__ */ 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)}`);
192
+ err.cause = error;
193
+ throw err;
194
+ }
195
+ return {
196
+ formattedString: inputDataString,
197
+ type,
198
+ format,
199
+ data: parsedData
200
+ };
201
+ };
202
+ //#endregion
203
+ //#region src/core/core_valibot_schemas.ts
204
+ const vBase64 = valibot.pipe(valibot.string(), valibot.base64());
205
+ const vCreateSchema_TypeAndFormatPrefixedDataString = ({ type, format, typeKind, formatKind }) => {
206
+ const _typeKind = typeKind ?? "data_type";
207
+ const _formatKind = formatKind ?? "data_format";
208
+ return valibot.pipe(valibot.custom((input) => {
209
+ if (typeof input !== "string") return false;
210
+ const [typePart, formatPart, dataPart] = input.split("::");
211
+ return typePart === type && formatPart === format && typeof dataPart === "string";
212
+ }, `Invalid format, expected '<${_typeKind}>::<${_formatKind}>::<value>' where "${_typeKind}" is "${type}", "${_formatKind}" is "${format}", and "value" is a string in the specified format`));
213
+ };
214
+ //#endregion
215
+ //#region src/crypto/crypto.schema.ts
216
+ let ECryptoKeyAlgo = /* @__PURE__ */ function(ECryptoKeyAlgo) {
217
+ ECryptoKeyAlgo["ed25519"] = "ed25519";
218
+ ECryptoKeyAlgo["x25519"] = "x25519";
219
+ return ECryptoKeyAlgo;
220
+ }({});
221
+ let ECryptoKeyFormat = /* @__PURE__ */ function(ECryptoKeyFormat) {
222
+ ECryptoKeyFormat["raw_base64"] = "raw_base64";
223
+ ECryptoKeyFormat["jwk"] = "jwk";
224
+ return ECryptoKeyFormat;
225
+ }({});
226
+ const vSerializedCryptoKeyDataEd25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString({
227
+ format: "raw_base64",
228
+ type: "ed25519",
229
+ typeKind: "algo"
230
+ });
231
+ const vSerializedCryptoKeyDataEd25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString({
232
+ format: "jwk",
233
+ type: "ed25519",
234
+ typeKind: "algo",
235
+ transformJson: true
236
+ });
237
+ const vSerializedCryptoKeyDataX25519_Raw = vCreateSchema_TypeAndFormatPrefixedDataString({
238
+ format: "raw_base64",
239
+ type: "x25519",
240
+ typeKind: "algo"
241
+ });
242
+ const vSerializedCryptoKeyDataX25519_Jwk = vCreateSchema_TypeAndFormatPrefixedDataString({
243
+ format: "jwk",
244
+ type: "x25519",
245
+ typeKind: "algo",
246
+ transformJson: true
247
+ });
248
+ const vCryptoKeyPairDataX25519 = valibot.object({
249
+ publicKey: vSerializedCryptoKeyDataX25519_Raw,
250
+ privateKey: vSerializedCryptoKeyDataX25519_Jwk
251
+ });
252
+ const vCryptoKeyPairDataEd25519 = valibot.object({
253
+ publicKey: vSerializedCryptoKeyDataEd25519_Raw,
254
+ privateKey: vSerializedCryptoKeyDataEd25519_Jwk
255
+ });
256
+ const vVerifyChallengeWithSignature_Input = valibot.object({
257
+ challenge: valibot.string(),
258
+ signatureBase64: vBase64
259
+ });
260
+ const vVerifyChallengeWithSignature_WithThrow_Input = valibot.intersect([vVerifyChallengeWithSignature_Input, valibot.object({ throwOnInvalid: valibot.optional(valibot.boolean()) })]);
261
+ const vEncryptedAesGcmPayload = valibot.object({
262
+ nonce: vBase64,
263
+ ciphertext: vBase64
264
+ });
265
+ //#endregion
266
+ //#region src/crypto/crypto.converters.ts
267
+ /**
268
+ *
269
+ * [CRYPTO ALGO] ED25519
270
+ *
271
+ */
272
+ const convertEd25519RawDataStringToObject = createDataStringConverter_stringToObject();
273
+ const convertEd25519JwkDataStringToObject = createDataStringConverter_stringToObject({ transformJson: true });
274
+ const convertEd25519FormattedStringToObject = createDataStringConverter_stringToObject({ transformJsonForFormats: ["jwk"] });
275
+ const convertEd25519RawDataStringToSerializedKeyData = (input) => {
276
+ return {
277
+ prefixed: input,
278
+ transformed: convertEd25519RawDataStringToObject(input)
279
+ };
280
+ };
281
+ const convertEd25519JwkDataStringToSerializedKeyData = (input) => {
282
+ return {
283
+ prefixed: input,
284
+ transformed: convertEd25519JwkDataStringToObject(input)
285
+ };
286
+ };
287
+ const convertEd25519FormattedStringToSerializedKeyData = (input) => {
288
+ return convertEd25519FormattedStringToObject(input);
289
+ };
290
+ /**
291
+ *
292
+ * [CRYPTO ALGO] X25519
293
+ *
294
+ */
295
+ const convertX25519RawDataStringToObject = createDataStringConverter_stringToObject();
296
+ const convertX25519JwkDataStringToObject = createDataStringConverter_stringToObject({ transformJson: true });
297
+ const convertX25519FormattedStringToObject = createDataStringConverter_stringToObject({ transformJsonForFormats: ["jwk"] });
298
+ const convertX25519RawDataStringToSerializedKeyData = (input) => {
299
+ return {
300
+ prefixed: input,
301
+ transformed: convertX25519RawDataStringToObject(input)
302
+ };
303
+ };
304
+ const convertX25519JwkDataStringToSerializedKeyData = (input) => {
305
+ return {
306
+ prefixed: input,
307
+ transformed: convertX25519JwkDataStringToObject(input)
308
+ };
309
+ };
310
+ const convertX25519FormattedStringToSerializedKeyData = (input) => {
311
+ return convertX25519FormattedStringToObject(input);
312
+ };
313
+ //#endregion
314
+ //#region src/crypto/ed25519/importEd25519Key.ts
315
+ const fromBase64$1 = async (dataBase64, keyUsage, extractable) => {
316
+ const keyBuffer = Uint8Array.from(_scure_base.base64.decode(dataBase64));
317
+ return await crypto.subtle.importKey("raw", keyBuffer, { name: "Ed25519" }, extractable, keyUsage);
318
+ };
319
+ const fromJwk$1 = async (jwk, keyUsage, extractable = true) => {
320
+ return await crypto.subtle.importKey("jwk", jwk, { name: "Ed25519" }, extractable, keyUsage);
321
+ };
322
+ const fromSerializedObject$1 = async (serialized, keyUsage, extractable = true) => {
323
+ if (serialized.format === "jwk") return await fromJwk$1(serialized.data, keyUsage, extractable);
324
+ return await fromBase64$1(serialized.data, keyUsage, extractable);
325
+ };
326
+ const fromFormattedString$1 = async (dataString, keyUsage, extractable = true) => {
327
+ return await fromSerializedObject$1(convertEd25519FormattedStringToSerializedKeyData(dataString), keyUsage, extractable);
328
+ };
329
+ const extractableOrNonExtractable$1 = (keyUsage, func) => ({
330
+ extractable: (input) => func(input, keyUsage, true),
331
+ nonExtractable: (input) => func(input, keyUsage, false)
332
+ });
333
+ const importEd25519Key = {
334
+ private: {
335
+ fromFormattedString: extractableOrNonExtractable$1(["sign"], fromFormattedString$1),
336
+ fromSerializedObject: extractableOrNonExtractable$1(["sign"], fromSerializedObject$1),
337
+ fromJwk: extractableOrNonExtractable$1(["sign"], fromJwk$1)
338
+ },
339
+ public: {
340
+ fromBase64: extractableOrNonExtractable$1(["verify"], fromBase64$1),
341
+ fromFormattedString: extractableOrNonExtractable$1(["verify"], fromFormattedString$1),
342
+ fromSerializedObject: extractableOrNonExtractable$1(["verify"], fromSerializedObject$1),
343
+ fromJwk: extractableOrNonExtractable$1(["verify"], fromJwk$1)
344
+ }
345
+ };
346
+ //#endregion
347
+ //#region src/crypto/ed25519/serializeEd25519Key_Jwk.ts
348
+ const serializeEd25519Key_Jwk = async (key) => {
349
+ const keyJwk = await crypto.subtle.exportKey("jwk", key);
350
+ const prefixed = `ed25519::jwk::${JSON.stringify(keyJwk)}`;
351
+ return {
352
+ transformed: {
353
+ formattedString: prefixed,
354
+ type: "ed25519",
355
+ data: keyJwk,
356
+ format: "jwk"
357
+ },
358
+ prefixed
359
+ };
360
+ };
361
+ //#endregion
362
+ //#region src/crypto/ed25519/serializeEd25519Key_Raw.ts
363
+ const serializeEd25519Key_Raw = async (publicKey) => {
364
+ const publicKeyBuffer = await crypto.subtle.exportKey("raw", publicKey);
365
+ const publicKeyBase64 = _scure_base.base64.encode(new Uint8Array(publicKeyBuffer));
366
+ const prefixed = `ed25519::raw_base64::${publicKeyBase64}`;
367
+ return {
368
+ transformed: {
369
+ formattedString: prefixed,
370
+ type: "ed25519",
371
+ data: publicKeyBase64,
372
+ format: "raw_base64"
373
+ },
374
+ prefixed
375
+ };
376
+ };
377
+ //#endregion
378
+ //#region src/crypto/ed25519/verifyWithKeyEd25519.ts
379
+ const verifyWithKeyEd25519 = async ({ challenge, signatureBase64, publicKey }) => {
380
+ const signatureBuffer = Uint8Array.from(_scure_base.base64.decode(signatureBase64));
381
+ const challengeBuffer = new TextEncoder().encode(challenge);
382
+ return await crypto.subtle.verify({ name: "ED25519" }, publicKey, signatureBuffer, challengeBuffer);
383
+ };
384
+ //#endregion
385
+ //#region src/crypto/x25519/generateX25519KeyPair.ts
386
+ const generateX25519KeyPair = async () => {
387
+ return await crypto.subtle.generateKey({ name: "X25519" }, true, ["deriveKey", "deriveBits"]);
388
+ };
389
+ //#endregion
390
+ //#region src/crypto/x25519/importX25519Key.ts
391
+ const fromBase64 = async (dataBase64, keyUsage, extractable) => {
392
+ const keyBuffer = Uint8Array.from(_scure_base.base64.decode(dataBase64));
393
+ return await crypto.subtle.importKey("raw", keyBuffer, { name: "X25519" }, extractable, keyUsage);
394
+ };
395
+ const fromJwk = async (jwk, keyUsage, extractable = true) => {
396
+ return await crypto.subtle.importKey("jwk", jwk, { name: "X25519" }, extractable, keyUsage);
397
+ };
398
+ const fromSerializedObject = async (serialized, keyUsage, extractable = true) => {
399
+ if (serialized.format === "jwk") return await fromJwk(serialized.data, keyUsage, extractable);
400
+ return await fromBase64(serialized.data, keyUsage, extractable);
401
+ };
402
+ const fromFormattedString = async (dataString, keyUsage, extractable = true) => {
403
+ return await fromSerializedObject(convertX25519FormattedStringToSerializedKeyData(dataString), keyUsage, extractable);
404
+ };
405
+ const extractableOrNonExtractable = (keyUsage, func) => ({
406
+ extractable: (input) => func(input, keyUsage, true),
407
+ nonExtractable: (input) => func(input, keyUsage, false)
408
+ });
409
+ const importX25519Key = {
410
+ private: {
411
+ fromFormattedString: extractableOrNonExtractable(["deriveKey", "deriveBits"], fromFormattedString),
412
+ fromSerializedObject: extractableOrNonExtractable(["deriveKey", "deriveBits"], fromSerializedObject),
413
+ fromJwk: extractableOrNonExtractable(["deriveKey", "deriveBits"], fromJwk)
414
+ },
415
+ public: {
416
+ fromBase64: extractableOrNonExtractable([], fromBase64),
417
+ fromFormattedString: extractableOrNonExtractable([], fromFormattedString),
418
+ fromSerializedObject: extractableOrNonExtractable([], fromSerializedObject),
419
+ fromJwk: extractableOrNonExtractable([], fromJwk)
420
+ }
421
+ };
422
+ //#endregion
423
+ //#region src/crypto/x25519/serializeX25519Key_Jwk.ts
424
+ const serializeX25519Key_Jwk = async (key) => {
425
+ const publicKeyJwk = await crypto.subtle.exportKey("jwk", key);
426
+ const prefixed = `x25519::jwk::${JSON.stringify(publicKeyJwk)}`;
427
+ return {
428
+ transformed: {
429
+ formattedString: prefixed,
430
+ type: "x25519",
431
+ data: publicKeyJwk,
432
+ format: "jwk"
433
+ },
434
+ prefixed
435
+ };
436
+ };
437
+ //#endregion
438
+ //#region src/crypto/x25519/serializeX25519Key_Raw.ts
439
+ const serializeX25519Key_Raw = async (key) => {
440
+ const publicKeyBuffer = await crypto.subtle.exportKey("raw", key);
441
+ const publicKeyBase64 = _scure_base.base64.encode(new Uint8Array(publicKeyBuffer));
442
+ const prefixed = `x25519::raw_base64::${publicKeyBase64}`;
443
+ return {
444
+ transformed: {
445
+ formattedString: prefixed,
446
+ type: "x25519",
447
+ data: publicKeyBase64,
448
+ format: "raw_base64"
449
+ },
450
+ prefixed
451
+ };
452
+ };
453
+ //#endregion
454
+ //#region src/crypto/client_key_link/ClientCryptoKeyLink.ts
455
+ var ClientCryptoKeyLink = class {
456
+ localExchangeKeyPair;
457
+ localVerifyKeyPair;
458
+ linkedClientKeys = /* @__PURE__ */ new Map();
459
+ storage;
460
+ initialized = false;
461
+ initializePromise;
462
+ localExchangeKeyPairPromise;
463
+ localVerifyKeyPairPromise;
464
+ constructor({ storageAdapter } = {}) {
465
+ if (storageAdapter != null) this.storage = createTypedStorage({ storageAdapter });
466
+ }
467
+ /**
468
+ * Loads the local key pairs and any linked client public keys from storage (when a storage
469
+ * adapter was provided), generating and persisting fresh local key pairs if none exist yet.
470
+ *
471
+ * Must be called (and awaited) before any sign/verify/encrypt/decrypt operation.
472
+ */
473
+ async initialize() {
474
+ if (this.initialized) return;
475
+ this.initializePromise ??= this.runInitialize();
476
+ try {
477
+ await this.initializePromise;
478
+ } finally {
479
+ this.initializePromise = void 0;
480
+ }
481
+ }
482
+ async runInitialize() {
483
+ await this.loadStoredLocalKeys();
484
+ await this.loadLinkedClients();
485
+ this.initialized = true;
486
+ }
487
+ /**
488
+ * Loads the local key pairs from storage if they were previously persisted. Does NOT generate
489
+ * fresh keys — local identity is created lazily on first use (see {@link ensureLocalExchangeKeyPair}
490
+ * / {@link ensureLocalVerifyKeyPair}), so a verify-only or otherwise key-less consumer never
491
+ * generates or stores keys it does not need.
492
+ */
493
+ async loadStoredLocalKeys() {
494
+ const storedExchange = await this.storage?.getJson("localExchangeKeyPair");
495
+ if (storedExchange != null) this.localExchangeKeyPair = {
496
+ privateKey: await importX25519Key.private.fromFormattedString.extractable(storedExchange.privateKey),
497
+ publicKey: await importX25519Key.public.fromFormattedString.extractable(storedExchange.publicKey)
498
+ };
499
+ const storedVerify = await this.storage?.getJson("localVerifyKeyPair");
500
+ if (storedVerify != null) this.localVerifyKeyPair = {
501
+ privateKey: await importEd25519Key.private.fromFormattedString.extractable(storedVerify.privateKey),
502
+ publicKey: await importEd25519Key.public.fromFormattedString.extractable(storedVerify.publicKey)
503
+ };
504
+ }
505
+ /**
506
+ * Returns the local exchange (X25519) key pair, generating and persisting it on first use.
507
+ * Concurrent callers share a single generation.
508
+ */
509
+ async ensureLocalExchangeKeyPair() {
510
+ if (this.localExchangeKeyPair != null) return this.localExchangeKeyPair;
511
+ this.localExchangeKeyPairPromise ??= (async () => {
512
+ const keyPair = await generateX25519KeyPair();
513
+ this.localExchangeKeyPair = keyPair;
514
+ if (this.storage != null) await this.storage.setJson("localExchangeKeyPair", await this.serializeExchangeKeyPair(keyPair));
515
+ return keyPair;
516
+ })();
517
+ try {
518
+ return await this.localExchangeKeyPairPromise;
519
+ } finally {
520
+ this.localExchangeKeyPairPromise = void 0;
521
+ }
522
+ }
523
+ /**
524
+ * Returns the local verify (Ed25519) key pair, generating and persisting it on first use.
525
+ * Concurrent callers share a single generation.
526
+ */
527
+ async ensureLocalVerifyKeyPair() {
528
+ if (this.localVerifyKeyPair != null) return this.localVerifyKeyPair;
529
+ this.localVerifyKeyPairPromise ??= (async () => {
530
+ const keyPair = await generateEd25519KeyPair();
531
+ this.localVerifyKeyPair = keyPair;
532
+ if (this.storage != null) await this.storage.setJson("localVerifyKeyPair", await this.serializeVerifyKeyPair(keyPair));
533
+ return keyPair;
534
+ })();
535
+ try {
536
+ return await this.localVerifyKeyPairPromise;
537
+ } finally {
538
+ this.localVerifyKeyPairPromise = void 0;
539
+ }
540
+ }
541
+ async loadLinkedClients() {
542
+ const storedLinkedClients = await this.storage?.getJson("linkedClientPublicKeys");
543
+ if (storedLinkedClients == null) return;
544
+ for (const [linkedClientId, publicKeys] of Object.entries(storedLinkedClients)) await this.linkClient({
545
+ linkedClientId,
546
+ verifyPublicKey: publicKeys.verifyPublicKey,
547
+ exchangePublicKey: publicKeys.exchangePublicKey,
548
+ saltString: publicKeys.saltString,
549
+ infoString: publicKeys.infoString,
550
+ bindVerifyKeysIntoDerivation: publicKeys.bindVerifyKeysIntoDerivation
551
+ });
552
+ }
553
+ async serializeExchangeKeyPair(keyPair) {
554
+ return {
555
+ publicKey: (await serializeX25519Key_Raw(keyPair.publicKey)).prefixed,
556
+ privateKey: (await serializeX25519Key_Jwk(keyPair.privateKey)).prefixed
557
+ };
558
+ }
559
+ async serializeVerifyKeyPair(keyPair) {
560
+ return {
561
+ publicKey: (await serializeEd25519Key_Raw(keyPair.publicKey)).prefixed,
562
+ privateKey: (await serializeEd25519Key_Jwk(keyPair.privateKey)).prefixed
563
+ };
564
+ }
565
+ /**
566
+ * The local public keys that should be shared with a linked client so that it can verify this
567
+ * client's signatures and derive a shared encryption key. Generates the local identity on first
568
+ * use.
569
+ */
570
+ async getLocalPublicKeys() {
571
+ return {
572
+ verifyPublicKey: await this.getLocalVerifyPublicKey(),
573
+ exchangePublicKey: await this.getLocalExchangePublicKey()
574
+ };
575
+ }
576
+ /**
577
+ * The local exchange (X25519) public key, generating the exchange key pair on first use. Does not
578
+ * touch the verify key pair — useful for an exchange-only consumer (e.g. a bridge) that never
579
+ * signs.
580
+ */
581
+ async getLocalExchangePublicKey() {
582
+ return (await serializeX25519Key_Raw((await this.ensureLocalExchangeKeyPair()).publicKey)).prefixed;
583
+ }
584
+ /**
585
+ * The local verify (Ed25519) public key, generating the verify key pair on first use. Does not
586
+ * touch the exchange key pair.
587
+ */
588
+ async getLocalVerifyPublicKey() {
589
+ return (await serializeEd25519Key_Raw((await this.ensureLocalVerifyKeyPair()).publicKey)).prefixed;
590
+ }
591
+ /**
592
+ * Registers (or updates) the public keys of a linked client in memory only — nothing is written
593
+ * to storage. Use this for ephemeral links (e.g. a per-session bridge or end-to-end peer keyed by
594
+ * a session salt/info), so the derived shared key never outlives the process.
595
+ *
596
+ * Re-linking with a new exchange public key, salt, or info invalidates any previously cached
597
+ * shared key for the link.
598
+ */
599
+ async linkClient({ linkedClientId, verifyPublicKey, exchangePublicKey, saltString, infoString, bindVerifyKeysIntoDerivation }) {
600
+ const existing = this.linkedClientKeys.get(linkedClientId);
601
+ const verify = verifyPublicKey != null ? {
602
+ publicKey: await importEd25519Key.public.fromFormattedString.extractable(verifyPublicKey),
603
+ publicKeySerialized: verifyPublicKey
604
+ } : existing?.verify;
605
+ const verifyKeyChanged = verifyPublicKey != null && verifyPublicKey !== existing?.verify?.publicKeySerialized;
606
+ let exchange = existing?.exchange;
607
+ if (exchangePublicKey != null || saltString !== void 0 || infoString !== void 0 || bindVerifyKeysIntoDerivation !== void 0) {
608
+ const nextPublicKeySerialized = exchangePublicKey ?? existing?.exchange?.publicKeySerialized;
609
+ if (nextPublicKeySerialized == null) throw new Error(`ClientCryptoKeyLink: Cannot set salt/info for ${linkedClientId} without an exchange public key`);
610
+ const nextSalt = saltString !== void 0 ? saltString : existing?.exchange?.saltString;
611
+ const nextInfo = infoString !== void 0 ? infoString : existing?.exchange?.infoString;
612
+ const nextBind = bindVerifyKeysIntoDerivation !== void 0 ? bindVerifyKeysIntoDerivation : existing?.exchange?.bindVerifyKeysIntoDerivation;
613
+ exchange = {
614
+ publicKey: exchangePublicKey != null ? await importX25519Key.public.fromFormattedString.extractable(exchangePublicKey) : existing.exchange.publicKey,
615
+ publicKeySerialized: nextPublicKeySerialized,
616
+ saltString: nextSalt,
617
+ infoString: nextInfo,
618
+ bindVerifyKeysIntoDerivation: nextBind,
619
+ sharedEncryptKey: nextPublicKeySerialized === existing?.exchange?.publicKeySerialized && nextSalt === existing?.exchange?.saltString && nextInfo === existing?.exchange?.infoString && nextBind === existing?.exchange?.bindVerifyKeysIntoDerivation && !(nextBind === true && verifyKeyChanged) ? existing?.exchange?.sharedEncryptKey : void 0
620
+ };
621
+ } else if (exchange?.bindVerifyKeysIntoDerivation === true && verifyKeyChanged && exchange.sharedEncryptKey != null) exchange = {
622
+ ...exchange,
623
+ sharedEncryptKey: void 0
624
+ };
625
+ this.linkedClientKeys.set(linkedClientId, {
626
+ verify,
627
+ exchange
628
+ });
629
+ }
630
+ /**
631
+ * Like {@link linkClient}, but also persists the linked client's public keys (and salt/info) to
632
+ * storage so the link survives a reload.
633
+ *
634
+ * NOTE: salt/info are written in plaintext. When they are session secrets (e.g. a partner secret
635
+ * or bridge salt), prefer {@link linkClient} and re-establish the link per session instead.
636
+ */
637
+ async linkClientAndStore(input) {
638
+ await this.linkClient(input);
639
+ if (this.storage == null) return;
640
+ const { linkedClientId, verifyPublicKey, exchangePublicKey, saltString, infoString, bindVerifyKeysIntoDerivation } = input;
641
+ await this.storage.updateJsonWithDef("linkedClientPublicKeys", {}, (current) => ({
642
+ ...current,
643
+ [linkedClientId]: {
644
+ ...current[linkedClientId],
645
+ ...verifyPublicKey != null ? { verifyPublicKey } : {},
646
+ ...exchangePublicKey != null ? { exchangePublicKey } : {},
647
+ ...saltString !== void 0 ? { saltString } : {},
648
+ ...infoString !== void 0 ? { infoString } : {},
649
+ ...bindVerifyKeysIntoDerivation !== void 0 ? { bindVerifyKeysIntoDerivation } : {}
650
+ }
651
+ }));
652
+ }
653
+ /**
654
+ * Whether a linked client is currently registered (in memory) under this id.
655
+ */
656
+ hasLinkedClient(linkedClientId) {
657
+ return this.linkedClientKeys.has(linkedClientId);
658
+ }
659
+ /**
660
+ * The serialized public keys registered for a linked client, or undefined when the client is not
661
+ * linked. Useful when a holder needs to relay a linked client's keys onward (e.g. a backend
662
+ * relaying a wallet's verify key to a partner).
663
+ */
664
+ getLinkedClientPublicKeys(linkedClientId) {
665
+ const linkedClient = this.linkedClientKeys.get(linkedClientId);
666
+ if (linkedClient == null) return;
667
+ return {
668
+ verifyPublicKey: linkedClient.verify?.publicKeySerialized,
669
+ exchangePublicKey: linkedClient.exchange?.publicKeySerialized
670
+ };
671
+ }
672
+ /**
673
+ * Removes a single linked client from memory and, when storage is available, from persisted
674
+ * state. Any cached shared key for the link is dropped with it.
675
+ */
676
+ async unlinkClient(linkedClientId) {
677
+ this.linkedClientKeys.delete(linkedClientId);
678
+ if (this.storage != null) await this.storage.updateJson("linkedClientPublicKeys", (current) => {
679
+ if (current == null) return {};
680
+ const { [linkedClientId]: _removed, ...rest } = current;
681
+ return rest;
682
+ });
683
+ }
684
+ /**
685
+ * Removes all linked clients from memory and persisted state, while keeping the local identity
686
+ * key pairs intact.
687
+ */
688
+ async unlinkAllClients() {
689
+ this.linkedClientKeys.clear();
690
+ if (this.storage != null) await this.storage.setJson("linkedClientPublicKeys", {});
691
+ }
692
+ /**
693
+ * Wipes everything this instance owns — local identity key pairs and all linked clients, in
694
+ * memory and in storage. After a reset, {@link initialize} must be called again before use (it
695
+ * will generate a fresh local identity).
696
+ *
697
+ * Only the keys owned by this util are removed, so a shared storage adapter's other data is left
698
+ * untouched.
699
+ */
700
+ async reset() {
701
+ this.linkedClientKeys.clear();
702
+ this.localExchangeKeyPair = void 0;
703
+ this.localVerifyKeyPair = void 0;
704
+ this.initialized = false;
705
+ if (this.storage != null) {
706
+ await this.storage.removeItem("linkedClientPublicKeys");
707
+ await this.storage.removeItem("localExchangeKeyPair");
708
+ await this.storage.removeItem("localVerifyKeyPair");
709
+ }
710
+ }
711
+ getLinkedClient(linkedClientId) {
712
+ const linkedClient = this.linkedClientKeys.get(linkedClientId);
713
+ if (linkedClient == null) throw new Error(`ClientCryptoKeyLink: No linked client for ${linkedClientId}`);
714
+ return linkedClient;
715
+ }
716
+ async getAesGcmKeyForLinkedClient(externalClientSourceId) {
717
+ const linkedClient = this.getLinkedClient(externalClientSourceId);
718
+ if (linkedClient.exchange?.sharedEncryptKey != null) return linkedClient.exchange.sharedEncryptKey;
719
+ if (linkedClient.exchange?.publicKey == null) throw new Error(`ClientCryptoKeyLink: No public exchange key set for ${externalClientSourceId}`);
720
+ const localExchangeKeyPair = await this.ensureLocalExchangeKeyPair();
721
+ let infoString = linkedClient.exchange.infoString;
722
+ if (linkedClient.exchange.bindVerifyKeysIntoDerivation === true) {
723
+ const linkedVerifyPublicKey = linkedClient.verify?.publicKeySerialized;
724
+ if (linkedVerifyPublicKey == null) throw new Error(`ClientCryptoKeyLink: Link for ${externalClientSourceId} binds verify keys into the derivation, but no verify public key is set`);
725
+ infoString = buildVerifyKeyBoundInfoString({
726
+ infoString: linkedClient.exchange.infoString,
727
+ verifyPublicKeys: [await this.getLocalVerifyPublicKey(), linkedVerifyPublicKey]
728
+ });
729
+ }
730
+ const sharedEncryptKey = await createAesGcmKeyFromX25519Keys({
731
+ internalX25519PrivateKey: localExchangeKeyPair.privateKey,
732
+ externalX25519PublicKey: linkedClient.exchange.publicKey,
733
+ saltString: linkedClient.exchange.saltString,
734
+ infoString
735
+ });
736
+ this.linkedClientKeys.set(externalClientSourceId, {
737
+ ...linkedClient,
738
+ exchange: {
739
+ ...linkedClient.exchange,
740
+ sharedEncryptKey
741
+ }
742
+ });
743
+ return sharedEncryptKey;
744
+ }
745
+ async encryptDataForLinkedClient({ dataToEncrypt, linkedClientId }) {
746
+ return await encryptTextDataWithAesGcmKey({
747
+ dataToEncrypt,
748
+ aesGcmKey: await this.getAesGcmKeyForLinkedClient(linkedClientId)
749
+ });
750
+ }
751
+ async decryptDataFromLinkedClient({ dataToDecrypt, linkedClientId }) {
752
+ return await decryptTextDataWithAesGcmKey({
753
+ dataToDecrypt,
754
+ aesGcmKey: await this.getAesGcmKeyForLinkedClient(linkedClientId)
755
+ });
756
+ }
757
+ /**
758
+ * Bytes counterpart of {@link encryptDataForLinkedClient} — encrypts raw bytes with the shared
759
+ * AES-GCM key, returning a binary nonce + ciphertext. Use it for binary channels (e.g. msgpack
760
+ * WebSocket frames) to avoid base64 inflation.
761
+ */
762
+ async encryptBytesForLinkedClient({ dataToEncrypt, linkedClientId }) {
763
+ return await encryptBytesWithAesGcmKey({
764
+ dataToEncrypt,
765
+ aesGcmKey: await this.getAesGcmKeyForLinkedClient(linkedClientId)
766
+ });
767
+ }
768
+ /** Bytes counterpart of {@link decryptDataFromLinkedClient}. */
769
+ async decryptBytesFromLinkedClient({ dataToDecrypt, linkedClientId }) {
770
+ return await decryptBytesWithAesGcmKey({
771
+ dataToDecrypt,
772
+ aesGcmKey: await this.getAesGcmKeyForLinkedClient(linkedClientId)
773
+ });
774
+ }
775
+ async signAndEncryptDataForLinkedClient({ dataToEncrypt, linkedClientId }) {
776
+ const { signatureBase64 } = await this.signChallenge([dataToEncrypt]);
777
+ return {
778
+ encryptedData: await this.encryptDataForLinkedClient({
779
+ dataToEncrypt,
780
+ linkedClientId
781
+ }),
782
+ signatureBase64
783
+ };
784
+ }
785
+ /**
786
+ * Decrypts a payload from a linked client and verifies that the decrypted plaintext was signed
787
+ * by that client. Counterpart to {@link signAndEncryptDataForLinkedClient}.
788
+ *
789
+ * Returns the decrypted `data` alongside `isValid` — the caller decides how to handle an invalid
790
+ * signature. (A tampered ciphertext fails earlier at AES-GCM decryption.)
791
+ */
792
+ async decryptAndVerifyDataFromLinkedClient({ dataToDecrypt, linkedClientId, signatureBase64 }) {
793
+ const data = await this.decryptDataFromLinkedClient({
794
+ dataToDecrypt,
795
+ linkedClientId
796
+ });
797
+ return {
798
+ data,
799
+ isValid: await this.verifyChallengeFromLinkedClient({
800
+ linkedClientId,
801
+ challenge: data,
802
+ signatureBase64
803
+ })
804
+ };
805
+ }
806
+ async signChallenge(challenge) {
807
+ if (challenge.length === 0) throw new Error("Challenge must contain at least one string");
808
+ const localVerifyKeyPair = await this.ensureLocalVerifyKeyPair();
809
+ const signature = challenge.length > 1 ? await signCombinedTextDataWithKeyEd25519(challenge, localVerifyKeyPair.privateKey) : await signTextDataWithKeyEd25519(challenge[0], localVerifyKeyPair.privateKey);
810
+ return { signatureBase64: _scure_base.base64.encode(signature) };
811
+ }
812
+ /**
813
+ * Verifies a signature over `challenge` against the linked client's verify (Ed25519) public key.
814
+ */
815
+ async verifyChallengeFromLinkedClient({ linkedClientId, challenge, signatureBase64 }) {
816
+ const linkedClient = this.getLinkedClient(linkedClientId);
817
+ if (linkedClient.verify?.publicKey == null) throw new Error(`ClientCryptoKeyLink: No verify public key set for ${linkedClientId}`);
818
+ return await verifyWithKeyEd25519({
819
+ challenge,
820
+ signatureBase64,
821
+ publicKey: linkedClient.verify.publicKey
822
+ });
823
+ }
824
+ };
825
+ //#endregion
826
+ //#region src/storage_adapter/storage_adapter.types.ts
827
+ let EStorageAdapterType = /* @__PURE__ */ function(EStorageAdapterType) {
828
+ EStorageAdapterType["string"] = "string";
829
+ EStorageAdapterType["json"] = "json";
830
+ return EStorageAdapterType;
831
+ }({});
832
+ //#endregion
833
+ //#region src/storage_adapter/StorageAdapter.ts
834
+ var StorageAdapter = class StorageAdapter {
835
+ implementation;
836
+ keyPrefix;
837
+ adapterStorage;
838
+ constructor({ methods, keyPrefix, trackKeysForClearing: trackKeys }) {
839
+ this.implementation = methods;
840
+ this.keyPrefix = keyPrefix ?? "";
841
+ const _trackKeys = trackKeys ?? true;
842
+ this.adapterStorage = _trackKeys ? createTypedStorage({ storageAdapter: new StorageAdapter({
843
+ methods,
844
+ keyPrefix,
845
+ trackKeysForClearing: false
846
+ }) }) : void 0;
847
+ }
848
+ getPrefixedKey(rawKey) {
849
+ return `${this.keyPrefix}${rawKey}`;
850
+ }
851
+ async trackUsedKey(rawKey) {
852
+ if (!this.adapterStorage) return;
853
+ await this.adapterStorage.updateJsonWithDef("__usedKeys__", [], (currentKeys) => {
854
+ if (!currentKeys.includes(rawKey)) return [...currentKeys, rawKey];
855
+ return currentKeys;
856
+ });
857
+ }
858
+ async untrackUsedKey(rawKey) {
859
+ if (!this.adapterStorage) return;
860
+ await this.adapterStorage.updateJsonWithDef("__usedKeys__", [], (currentKeys) => {
861
+ return currentKeys.filter((k) => k !== rawKey);
862
+ });
863
+ }
864
+ async clearAll() {
865
+ if (!this.adapterStorage) return;
866
+ const allKeys = await this.adapterStorage.getJsonOrDef("__usedKeys__", []) ?? [];
867
+ await Promise.all(allKeys.map(async (key) => {
868
+ await this.removeItem(key);
869
+ }));
870
+ await this.adapterStorage.setJson("__usedKeys__", []);
871
+ }
872
+ async removeItem(rawKey) {
873
+ await this.implementation.removeItem(this.getPrefixedKey(rawKey));
874
+ await this.untrackUsedKey(rawKey);
875
+ }
876
+ async setJson(rawKey, value) {
877
+ const key = this.getPrefixedKey(rawKey);
878
+ if (this.implementation.type === "string") await this.implementation.setItem(key, JSON.stringify(value));
879
+ else await this.implementation.setItem(key, value);
880
+ await this.trackUsedKey(rawKey);
881
+ }
882
+ async getJson(rawKey) {
883
+ const key = this.getPrefixedKey(rawKey);
884
+ if (this.implementation.type === "string") {
885
+ const val = await this.implementation.getItem(key);
886
+ if (val == null || val === "undefined" || val === "null") return;
887
+ return JSON.parse(val);
888
+ } else {
889
+ const val = await this.implementation.getItem(key);
890
+ if (val == null || val === "undefined" || val === "null") return;
891
+ return val;
892
+ }
893
+ }
894
+ async getJsonOrDef(rawKey, defVal) {
895
+ if (this.implementation.type === "string") {
896
+ const val = await this.implementation.getItem(this.getPrefixedKey(rawKey));
897
+ if (val == null || val === "undefined" || val === "null") return defVal;
898
+ return JSON.parse(val);
899
+ }
900
+ const val = await this.implementation.getItem(this.getPrefixedKey(rawKey));
901
+ if (val == null || val === "undefined" || val === "null") return defVal;
902
+ return val;
903
+ }
904
+ async updateJson(rawKey, updater) {
905
+ const newVal = updater(await this.getJson(rawKey));
906
+ await this.setJson(rawKey, newVal);
907
+ return newVal;
908
+ }
909
+ async updateJsonOrDef(rawKey, defVal, updater) {
910
+ const newVal = updater(await this.getJsonOrDef(rawKey, defVal));
911
+ await this.setJson(rawKey, newVal);
912
+ return newVal;
913
+ }
914
+ createJsonGetterSetter(rawKey) {
915
+ return {
916
+ get: () => this.getJson(rawKey),
917
+ set: (value) => this.setJson(rawKey, value)
918
+ };
919
+ }
920
+ };
921
+ //#endregion
922
+ //#region src/storage_adapter/specific/browser/browser_storage.ts
923
+ function createWebLocalStorageMethods(_localStorage) {
924
+ return {
925
+ type: "string",
926
+ getItem: async (key) => _localStorage.getItem(key),
927
+ setItem: async (key, value) => {
928
+ _localStorage.setItem(key, value);
929
+ },
930
+ removeItem: async (key) => {
931
+ _localStorage.removeItem(key);
932
+ }
933
+ };
934
+ }
935
+ const createWebLocalStorageAdapter = ({ localStorage: _localStorage, ...options }) => {
936
+ return new StorageAdapter({
937
+ methods: createWebLocalStorageMethods(_localStorage),
938
+ ...options
939
+ });
940
+ };
941
+ function createTypedWebLocalStorage(options) {
942
+ return createTypedStorage({ storageAdapter: createWebLocalStorageAdapter(options) });
943
+ }
944
+ function createWebSessionStorageMethods(_sessionStorage) {
945
+ return {
946
+ type: "string",
947
+ getItem: async (key) => _sessionStorage.getItem(key),
948
+ setItem: async (key, value) => {
949
+ _sessionStorage.setItem(key, value);
950
+ },
951
+ removeItem: async (key) => {
952
+ _sessionStorage.removeItem(key);
953
+ }
954
+ };
955
+ }
956
+ const createWebSessionStorageAdapter = ({ sessionStorage: _sessionStorage, ...options }) => {
957
+ return new StorageAdapter({
958
+ methods: createWebSessionStorageMethods(_sessionStorage),
959
+ ...options
960
+ });
961
+ };
962
+ function createTypedWebSessionStorage(options) {
963
+ return createTypedStorage({ storageAdapter: createWebSessionStorageAdapter(options) });
964
+ }
965
+ //#endregion
966
+ //#region src/storage_adapter/specific/cloudflare/durable_object/durable_object_storage.ts
967
+ function createDurableObjectStorageMethods(durableObjectStorage) {
968
+ return {
969
+ type: "json",
970
+ getItem: (key) => durableObjectStorage.get(key),
971
+ setItem: (key, value) => durableObjectStorage.put(key, value),
972
+ removeItem: async (key) => {
973
+ await durableObjectStorage.delete(key);
974
+ }
975
+ };
976
+ }
977
+ /**
978
+ * Wraps a Durable Object's storage in the generic StorageAdapter interface, e.g. for handing to a
979
+ * ClientCryptoKeyLink so it can persist its keys inside the DO's own storage.
980
+ */
981
+ const createDurableObjectStorageAdapter = ({ durableObjectStorage, ...options }) => {
982
+ return new StorageAdapter({
983
+ methods: createDurableObjectStorageMethods(durableObjectStorage),
984
+ ...options
985
+ });
986
+ };
987
+ function createDurableObjectTypedStorage(options) {
988
+ return createTypedStorage({ storageAdapter: createDurableObjectStorageAdapter(options) });
989
+ }
990
+ //#endregion
991
+ //#region src/storage_adapter/specific/cloudflare/kv/kv_storage.ts
992
+ function createKVStorageMethods({ kvNamespace, defaultPutOptions }) {
993
+ return {
994
+ type: "string",
995
+ getItem: (key) => kvNamespace.get(key),
996
+ setItem: (key, value) => kvNamespace.put(key, value, defaultPutOptions),
997
+ removeItem: (key) => kvNamespace.delete(key)
998
+ };
999
+ }
1000
+ /**
1001
+ * Wraps a Cloudflare KV namespace binding in the generic StorageAdapter interface, e.g. for handing
1002
+ * to a ClientCryptoKeyLink so it can persist its keys inside KV.
1003
+ */
1004
+ const createKVStorageAdapter = ({ kvNamespace, defaultPutOptions, ...options }) => {
1005
+ return new StorageAdapter({
1006
+ methods: createKVStorageMethods({
1007
+ kvNamespace,
1008
+ defaultPutOptions
1009
+ }),
1010
+ ...options
1011
+ });
1012
+ };
1013
+ function createKVTypedStorage(options) {
1014
+ return createTypedStorage({ storageAdapter: createKVStorageAdapter(options) });
1015
+ }
1016
+ //#endregion
1017
+ //#region src/storage_adapter/specific/memory/memory_storage.ts
1018
+ function createMemoryStorageMethods_string(memoryStorageMap = /* @__PURE__ */ new Map()) {
1019
+ return {
1020
+ type: "string",
1021
+ getItem: async (key) => memoryStorageMap.get(key) ?? null,
1022
+ setItem: async (key, value) => {
1023
+ memoryStorageMap.set(key, value);
1024
+ },
1025
+ removeItem: async (key) => {
1026
+ memoryStorageMap.delete(key);
1027
+ }
1028
+ };
1029
+ }
1030
+ const createMemoryStorageAdapter_string = (options) => {
1031
+ return new StorageAdapter({
1032
+ methods: createMemoryStorageMethods_string(options?.memoryStorageMap),
1033
+ ...options
1034
+ });
1035
+ };
1036
+ function createTypedMemoryStorage_string(options) {
1037
+ return createTypedStorage({ storageAdapter: createMemoryStorageAdapter_string(options) });
1038
+ }
1039
+ function createMemoryStorageMethods_json(memoryStorageMap = /* @__PURE__ */ new Map()) {
1040
+ return {
1041
+ type: "json",
1042
+ getItem: async (key) => memoryStorageMap.get(key),
1043
+ setItem: async (key, value) => {
1044
+ memoryStorageMap.set(key, value);
1045
+ },
1046
+ removeItem: async (key) => {
1047
+ memoryStorageMap.delete(key);
1048
+ }
1049
+ };
1050
+ }
1051
+ const createMemoryStorageAdapter_json = (options) => {
1052
+ return new StorageAdapter({
1053
+ methods: createMemoryStorageMethods_json(options?.memoryStorageMap),
1054
+ ...options
1055
+ });
1056
+ };
1057
+ function createTypedMemoryStorage_json(options) {
1058
+ return createTypedStorage({ storageAdapter: createMemoryStorageAdapter_json(options) });
1059
+ }
1060
+ //#endregion
1061
+ exports.ClientCryptoKeyLink = ClientCryptoKeyLink;
1062
+ exports.DEFAULT_COMBINED_TEXT_DATA_SEPARATOR = DEFAULT_COMBINED_TEXT_DATA_SEPARATOR;
1063
+ exports.ECryptoKeyAlgo = ECryptoKeyAlgo;
1064
+ exports.ECryptoKeyFormat = ECryptoKeyFormat;
1065
+ exports.EStorageAdapterType = EStorageAdapterType;
1066
+ exports.StorageAdapter = StorageAdapter;
1067
+ exports.buildVerifyKeyBoundInfoString = buildVerifyKeyBoundInfoString;
1068
+ exports.convertEd25519FormattedStringToObject = convertEd25519FormattedStringToObject;
1069
+ exports.convertEd25519FormattedStringToSerializedKeyData = convertEd25519FormattedStringToSerializedKeyData;
1070
+ exports.convertEd25519JwkDataStringToObject = convertEd25519JwkDataStringToObject;
1071
+ exports.convertEd25519JwkDataStringToSerializedKeyData = convertEd25519JwkDataStringToSerializedKeyData;
1072
+ exports.convertEd25519RawDataStringToObject = convertEd25519RawDataStringToObject;
1073
+ exports.convertEd25519RawDataStringToSerializedKeyData = convertEd25519RawDataStringToSerializedKeyData;
1074
+ exports.convertX25519FormattedStringToObject = convertX25519FormattedStringToObject;
1075
+ exports.convertX25519FormattedStringToSerializedKeyData = convertX25519FormattedStringToSerializedKeyData;
1076
+ exports.convertX25519JwkDataStringToObject = convertX25519JwkDataStringToObject;
1077
+ exports.convertX25519JwkDataStringToSerializedKeyData = convertX25519JwkDataStringToSerializedKeyData;
1078
+ exports.convertX25519RawDataStringToObject = convertX25519RawDataStringToObject;
1079
+ exports.convertX25519RawDataStringToSerializedKeyData = convertX25519RawDataStringToSerializedKeyData;
1080
+ exports.createAesGcmKeyFromX25519Keys = createAesGcmKeyFromX25519Keys;
1081
+ exports.createDurableObjectStorageAdapter = createDurableObjectStorageAdapter;
1082
+ exports.createDurableObjectStorageMethods = createDurableObjectStorageMethods;
1083
+ exports.createDurableObjectTypedStorage = createDurableObjectTypedStorage;
1084
+ exports.createKVStorageAdapter = createKVStorageAdapter;
1085
+ exports.createKVStorageMethods = createKVStorageMethods;
1086
+ exports.createKVTypedStorage = createKVTypedStorage;
1087
+ exports.createMemoryStorageAdapter_json = createMemoryStorageAdapter_json;
1088
+ exports.createMemoryStorageAdapter_string = createMemoryStorageAdapter_string;
1089
+ exports.createMemoryStorageMethods_json = createMemoryStorageMethods_json;
1090
+ exports.createMemoryStorageMethods_string = createMemoryStorageMethods_string;
1091
+ exports.createSharedBitsFromX25519 = createSharedBitsFromX25519;
1092
+ exports.createTypedMemoryStorage_json = createTypedMemoryStorage_json;
1093
+ exports.createTypedMemoryStorage_string = createTypedMemoryStorage_string;
1094
+ exports.createTypedStorage = createTypedStorage;
1095
+ exports.createTypedWebLocalStorage = createTypedWebLocalStorage;
1096
+ exports.createTypedWebSessionStorage = createTypedWebSessionStorage;
1097
+ exports.createWebLocalStorageAdapter = createWebLocalStorageAdapter;
1098
+ exports.createWebLocalStorageMethods = createWebLocalStorageMethods;
1099
+ exports.createWebSessionStorageAdapter = createWebSessionStorageAdapter;
1100
+ exports.createWebSessionStorageMethods = createWebSessionStorageMethods;
1101
+ exports.decryptBytesWithAesGcmKey = decryptBytesWithAesGcmKey;
1102
+ exports.decryptTextDataWithAesGcmKey = decryptTextDataWithAesGcmKey;
1103
+ exports.encryptBytesWithAesGcmKey = encryptBytesWithAesGcmKey;
1104
+ exports.encryptTextDataWithAesGcmKey = encryptTextDataWithAesGcmKey;
1105
+ exports.generateEd25519KeyPair = generateEd25519KeyPair;
1106
+ exports.generateX25519KeyPair = generateX25519KeyPair;
1107
+ exports.importEd25519Key = importEd25519Key;
1108
+ exports.importX25519Key = importX25519Key;
1109
+ exports.serializeEd25519Key_Jwk = serializeEd25519Key_Jwk;
1110
+ exports.serializeEd25519Key_Raw = serializeEd25519Key_Raw;
1111
+ exports.serializeX25519Key_Jwk = serializeX25519Key_Jwk;
1112
+ exports.serializeX25519Key_Raw = serializeX25519Key_Raw;
1113
+ exports.signCombinedTextDataWithKeyEd25519 = signCombinedTextDataWithKeyEd25519;
1114
+ exports.signTextDataWithKeyEd25519 = signTextDataWithKeyEd25519;
1115
+ exports.vCryptoKeyPairDataEd25519 = vCryptoKeyPairDataEd25519;
1116
+ exports.vCryptoKeyPairDataX25519 = vCryptoKeyPairDataX25519;
1117
+ exports.vEncryptedAesGcmPayload = vEncryptedAesGcmPayload;
1118
+ exports.vSerializedCryptoKeyDataEd25519_Jwk = vSerializedCryptoKeyDataEd25519_Jwk;
1119
+ exports.vSerializedCryptoKeyDataEd25519_Raw = vSerializedCryptoKeyDataEd25519_Raw;
1120
+ exports.vSerializedCryptoKeyDataX25519_Jwk = vSerializedCryptoKeyDataX25519_Jwk;
1121
+ exports.vSerializedCryptoKeyDataX25519_Raw = vSerializedCryptoKeyDataX25519_Raw;
1122
+ exports.vVerifyChallengeWithSignature_Input = vVerifyChallengeWithSignature_Input;
1123
+ exports.vVerifyChallengeWithSignature_WithThrow_Input = vVerifyChallengeWithSignature_WithThrow_Input;
1124
+ exports.verifyWithKeyEd25519 = verifyWithKeyEd25519;
1125
+
1126
+ //# sourceMappingURL=index.cjs.map