@alibarbar/common 1.1.1 → 1.1.3

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/dist/storage.cjs CHANGED
@@ -1,6 +1,16 @@
1
1
  'use strict';
2
2
 
3
- // src/helper/crypto/index.ts
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var JSEncrypt = require('jsencrypt');
6
+ var CryptoJS = require('crypto-js');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var JSEncrypt__default = /*#__PURE__*/_interopDefault(JSEncrypt);
11
+ var CryptoJS__default = /*#__PURE__*/_interopDefault(CryptoJS);
12
+
13
+ // src/helper/encryption/index.ts
4
14
  function base64Encode(data) {
5
15
  if (typeof data === "string") {
6
16
  return btoa(unescape(encodeURIComponent(data)));
@@ -12,954 +22,421 @@ function base64Encode(data) {
12
22
  }
13
23
  return btoa(binary);
14
24
  }
15
- function base64Decode(data) {
16
- try {
17
- return decodeURIComponent(escape(atob(data)));
18
- } catch {
19
- throw new Error("Invalid Base64 string");
20
- }
21
- }
22
- function generateRandomString(length, charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") {
23
- let result = "";
24
- for (let i = 0; i < length; i++) {
25
- result += charset.charAt(Math.floor(Math.random() * charset.length));
26
- }
27
- return result;
28
- }
29
- async function generateRSAKeyPair(modulusLength = 2048) {
30
- if (typeof crypto === "undefined" || !crypto.subtle) {
31
- throw new Error("Web Crypto API is not available");
32
- }
33
- const keyPair = await crypto.subtle.generateKey(
34
- {
35
- name: "RSA-OAEP",
36
- modulusLength,
37
- publicExponent: new Uint8Array([1, 0, 1]),
38
- hash: "SHA-256"
39
- },
40
- true,
41
- ["encrypt", "decrypt"]
42
- );
43
- return {
44
- publicKey: keyPair.publicKey,
45
- privateKey: keyPair.privateKey
46
- };
25
+ function generateRandomAESKeyString() {
26
+ return CryptoJS__default.default.lib.WordArray.random(256 / 8).toString();
47
27
  }
48
- async function rsaEncrypt(data, publicKey) {
49
- if (typeof crypto === "undefined" || !crypto.subtle) {
50
- throw new Error("Web Crypto API is not available");
51
- }
52
- const encoder = new TextEncoder();
53
- const dataBuffer = encoder.encode(data);
54
- const maxChunkSize = 245;
55
- const chunks = [];
56
- for (let i = 0; i < dataBuffer.length; i += maxChunkSize) {
57
- const chunk = dataBuffer.slice(i, i + maxChunkSize);
58
- const encrypted = await crypto.subtle.encrypt(
59
- {
60
- name: "RSA-OAEP"
61
- },
62
- publicKey,
63
- chunk
64
- );
65
- chunks.push(encrypted);
66
- }
67
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
68
- const merged = new Uint8Array(totalLength);
69
- let offset = 0;
70
- for (const chunk of chunks) {
71
- merged.set(new Uint8Array(chunk), offset);
72
- offset += chunk.byteLength;
73
- }
74
- return base64Encode(merged.buffer);
75
- }
76
- async function rsaDecrypt(encryptedData, privateKey) {
77
- if (typeof crypto === "undefined" || !crypto.subtle) {
78
- throw new Error("Web Crypto API is not available");
79
- }
80
- const binaryString = atob(encryptedData);
81
- const encryptedArray = new Uint8Array(binaryString.length);
82
- for (let i = 0; i < binaryString.length; i++) {
83
- encryptedArray[i] = binaryString.charCodeAt(i);
84
- }
85
- const chunkSize = 256;
86
- const chunks = [];
87
- for (let i = 0; i < encryptedArray.length; i += chunkSize) {
88
- const chunk = encryptedArray.slice(i, i + chunkSize);
89
- const decrypted = await crypto.subtle.decrypt(
90
- {
91
- name: "RSA-OAEP"
92
- },
93
- privateKey,
94
- chunk
28
+ function encryptJsonWithAES(data, aesKey) {
29
+ try {
30
+ const jsonString = JSON.stringify(data);
31
+ return CryptoJS__default.default.AES.encrypt(jsonString, aesKey).toString();
32
+ } catch (error) {
33
+ throw new Error(
34
+ "[encryption] AES encryptJsonWithAES failed: " + (error instanceof Error ? error.message : String(error))
95
35
  );
96
- const decoder = new TextDecoder();
97
- chunks.push(decoder.decode(decrypted));
98
- }
99
- return chunks.join("");
100
- }
101
- async function exportPublicKey(publicKey) {
102
- if (typeof crypto === "undefined" || !crypto.subtle) {
103
- throw new Error("Web Crypto API is not available");
104
36
  }
105
- const exported = await crypto.subtle.exportKey("spki", publicKey);
106
- return base64Encode(exported);
107
37
  }
108
- async function exportPrivateKey(privateKey) {
109
- if (typeof crypto === "undefined" || !crypto.subtle) {
110
- throw new Error("Web Crypto API is not available");
111
- }
112
- const exported = await crypto.subtle.exportKey("pkcs8", privateKey);
113
- return base64Encode(exported);
114
- }
115
- async function importPublicKey(keyData) {
116
- if (typeof crypto === "undefined" || !crypto.subtle) {
117
- throw new Error("Web Crypto API is not available");
118
- }
119
- const keyBuffer = base64Decode(keyData);
120
- const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
121
- return crypto.subtle.importKey(
122
- "spki",
123
- keyArray.buffer,
124
- {
125
- name: "RSA-OAEP",
126
- hash: "SHA-256"
127
- },
128
- true,
129
- ["encrypt"]
130
- );
131
- }
132
- async function importPrivateKey(keyData) {
133
- if (typeof crypto === "undefined" || !crypto.subtle) {
134
- throw new Error("Web Crypto API is not available");
135
- }
136
- const keyBuffer = base64Decode(keyData);
137
- const keyArray = new Uint8Array(keyBuffer.split("").map((char) => char.charCodeAt(0)));
138
- return crypto.subtle.importKey(
139
- "pkcs8",
140
- keyArray.buffer,
141
- {
142
- name: "RSA-OAEP",
143
- hash: "SHA-256"
144
- },
145
- true,
146
- ["decrypt"]
147
- );
148
- }
149
- async function generateHMACKey() {
150
- if (typeof crypto === "undefined" || !crypto.subtle) {
151
- throw new Error("Web Crypto API is not available");
152
- }
153
- return crypto.subtle.generateKey(
154
- {
155
- name: "HMAC",
156
- hash: "SHA-256"
157
- },
158
- true,
159
- ["sign", "verify"]
160
- );
161
- }
162
- async function computeHMAC(data, key) {
163
- if (typeof crypto === "undefined" || !crypto.subtle) {
164
- throw new Error("Web Crypto API is not available");
165
- }
166
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
167
- const signature = await crypto.subtle.sign("HMAC", key, buffer);
168
- return base64Encode(signature);
169
- }
170
- async function verifyHMAC(data, signature, key) {
171
- if (typeof crypto === "undefined" || !crypto.subtle) {
172
- throw new Error("Web Crypto API is not available");
173
- }
38
+ function decryptJsonWithAES(encryptedData, aesKey) {
174
39
  try {
175
- const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
176
- const signatureBuffer = new Uint8Array(
177
- atob(signature).split("").map((char) => char.charCodeAt(0))
40
+ const decrypted = CryptoJS__default.default.AES.decrypt(encryptedData, aesKey);
41
+ const jsonString = decrypted.toString(CryptoJS__default.default.enc.Utf8);
42
+ if (!jsonString) {
43
+ throw new Error("decrypted JSON string is empty");
44
+ }
45
+ return JSON.parse(jsonString);
46
+ } catch (error) {
47
+ throw new Error(
48
+ "[encryption] AES decryptJsonWithAES failed: " + (error instanceof Error ? error.message : String(error))
178
49
  );
179
- return await crypto.subtle.verify("HMAC", key, signatureBuffer, dataBuffer);
180
- } catch {
181
- return false;
182
- }
183
- }
184
- async function deriveKeyFromPassword(password, salt, iterations = 1e5, keyLength = 256) {
185
- if (typeof crypto === "undefined" || !crypto.subtle) {
186
- throw new Error("Web Crypto API is not available");
187
50
  }
188
- const saltBuffer = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
189
- const passwordKey = await crypto.subtle.importKey(
190
- "raw",
191
- new TextEncoder().encode(password),
192
- "PBKDF2",
193
- false,
194
- ["deriveBits", "deriveKey"]
195
- );
196
- return crypto.subtle.deriveKey(
197
- {
198
- name: "PBKDF2",
199
- salt: saltBuffer,
200
- iterations,
201
- hash: "SHA-256"
202
- },
203
- passwordKey,
204
- {
205
- name: "AES-GCM",
206
- length: keyLength
207
- },
208
- false,
209
- ["encrypt", "decrypt"]
210
- );
211
51
  }
212
- async function aesGCMEncrypt(data, key) {
213
- if (typeof crypto === "undefined" || !crypto.subtle) {
214
- throw new Error("Web Crypto API is not available");
52
+ function getEnvPublicKey() {
53
+ const key = undefined.VITE_RSA_PUBLIC_KEY?.trim();
54
+ if (!key) {
55
+ throw new Error(
56
+ "[encryption] VITE_RSA_PUBLIC_KEY is not set. Please configure RSA public key in environment variables."
57
+ );
215
58
  }
216
- const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
217
- const iv = crypto.getRandomValues(new Uint8Array(12));
218
- const encrypted = await crypto.subtle.encrypt(
219
- {
220
- name: "AES-GCM",
221
- iv
222
- },
223
- key,
224
- dataBuffer
225
- );
226
- return {
227
- encrypted: base64Encode(encrypted),
228
- iv: base64Encode(iv.buffer)
229
- };
59
+ return key;
230
60
  }
231
- async function aesGCMDecrypt(encryptedData, iv, key) {
232
- if (typeof crypto === "undefined" || !crypto.subtle) {
233
- throw new Error("Web Crypto API is not available");
61
+ function getEnvPrivateKey() {
62
+ const key = undefined.VITE_RSA_PRIVATE_KEY?.trim();
63
+ if (!key) {
64
+ throw new Error(
65
+ "[encryption] VITE_RSA_PRIVATE_KEY is not set. Please configure RSA private key in environment variables."
66
+ );
234
67
  }
235
- const encryptedBuffer = new Uint8Array(
236
- atob(encryptedData).split("").map((char) => char.charCodeAt(0))
237
- );
238
- const ivBuffer = new Uint8Array(
239
- atob(iv).split("").map((char) => char.charCodeAt(0))
240
- );
241
- const decrypted = await crypto.subtle.decrypt(
242
- {
243
- name: "AES-GCM",
244
- iv: ivBuffer
245
- },
246
- key,
247
- encryptedBuffer
248
- );
249
- return new TextDecoder().decode(decrypted);
68
+ return key;
250
69
  }
251
-
252
- // src/browser/SecureStorage/index.ts
253
- var globalKeyPair = null;
254
- var globalHMACKey = null;
255
- var keyPairInitialized = false;
256
- var initOptions = {
257
- autoGenerateKeys: true,
258
- persistKeys: false,
259
- keyStorageKey: void 0,
260
- // 将自动生成随机键名
261
- keyEncryptionPassword: void 0,
262
- pbkdf2Iterations: 1e5,
263
- keyModulusLength: 2048,
264
- enableHMAC: true,
265
- enableTimestampValidation: true,
266
- timestampMaxAge: 7 * 24 * 60 * 60 * 1e3,
267
- // 7 天
268
- isProduction: false
269
- };
270
- var actualKeyStorageKey = null;
271
- var keyUsageCount = 0;
272
- var initializationPromise = null;
273
- function generateKeyStorageKey() {
274
- return `_sk_${generateRandomString(32)}_${Date.now()}`;
70
+ function base64ToPem(base64Key, type) {
71
+ const chunks = [];
72
+ for (let i = 0; i < base64Key.length; i += 64) {
73
+ chunks.push(base64Key.slice(i, i + 64));
74
+ }
75
+ const body = chunks.join("\n");
76
+ const header = type === "PUBLIC" ? "-----BEGIN PUBLIC KEY-----" : "-----BEGIN PRIVATE KEY-----";
77
+ const footer = type === "PUBLIC" ? "-----END PUBLIC KEY-----" : "-----END PRIVATE KEY-----";
78
+ return `${header}
79
+ ${body}
80
+ ${footer}`;
275
81
  }
276
- async function initializeStorageKeys(options = {}) {
277
- if (options.forceReinitialize) {
278
- globalKeyPair = null;
279
- globalHMACKey = null;
280
- keyPairInitialized = false;
281
- actualKeyStorageKey = null;
282
- keyUsageCount = 0;
283
- initializationPromise = null;
284
- } else if (keyPairInitialized && globalKeyPair) {
285
- initOptions = { ...initOptions, ...options };
286
- return;
287
- }
288
- initOptions = { ...initOptions, ...options };
289
- if (initOptions.keyStorageKey) {
290
- actualKeyStorageKey = initOptions.keyStorageKey;
291
- } else {
292
- actualKeyStorageKey = generateKeyStorageKey();
293
- }
294
- if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
295
- try {
296
- const storedKeys = window.localStorage.getItem(actualKeyStorageKey);
297
- if (storedKeys) {
298
- const keyData = JSON.parse(storedKeys);
299
- if (keyData.encrypted && keyData.privateKeyEncrypted && keyData.salt) {
300
- if (!initOptions.keyEncryptionPassword) {
301
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
302
- console.error("Encrypted keys found but no password provided");
303
- }
304
- throw new Error("Password required to decrypt stored keys");
305
- }
306
- const saltArray = new Uint8Array(
307
- atob(keyData.salt).split("").map((char) => char.charCodeAt(0))
308
- );
309
- const iterations = keyData.pbkdf2Iterations || initOptions.pbkdf2Iterations;
310
- const derivedKey = await deriveKeyFromPassword(
311
- initOptions.keyEncryptionPassword,
312
- saltArray.buffer,
313
- iterations
314
- );
315
- const decryptedPrivateKey = await aesGCMDecrypt(
316
- keyData.privateKeyEncrypted,
317
- keyData.iv,
318
- derivedKey
319
- );
320
- globalKeyPair = {
321
- publicKey: await importPublicKey(keyData.publicKey),
322
- privateKey: await importPrivateKey(decryptedPrivateKey)
323
- };
324
- } else if (keyData.publicKey && keyData.privateKey) {
325
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
326
- console.warn(
327
- "\u26A0\uFE0F SECURITY WARNING: Loading unencrypted keys from storage. Consider re-initializing with password encryption."
328
- );
329
- }
330
- globalKeyPair = {
331
- publicKey: await importPublicKey(keyData.publicKey),
332
- privateKey: await importPrivateKey(keyData.privateKey)
333
- };
334
- }
335
- if (globalKeyPair) {
336
- keyPairInitialized = true;
337
- if (initOptions.enableHMAC && !globalHMACKey) {
338
- globalHMACKey = await generateHMACKey();
339
- }
340
- return;
341
- }
82
+ async function rsaEncrypt(plain, publicKeyPem) {
83
+ try {
84
+ const encrypt = new JSEncrypt__default.default();
85
+ let publicKeyString;
86
+ if (typeof publicKeyPem === "string") {
87
+ const trimmedKey = publicKeyPem.trim();
88
+ if (!trimmedKey) {
89
+ throw new Error("Public key string is empty");
342
90
  }
343
- } catch (error) {
344
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
345
- console.warn("Failed to load persisted keys, will generate new ones");
91
+ if (trimmedKey.includes("-----BEGIN")) {
92
+ publicKeyString = trimmedKey;
93
+ } else {
94
+ publicKeyString = base64ToPem(trimmedKey, "PUBLIC");
346
95
  }
347
- }
348
- }
349
- if (initOptions.autoGenerateKeys && !globalKeyPair) {
350
- try {
351
- globalKeyPair = await generateRSAKeyPair(initOptions.keyModulusLength);
352
- if (initOptions.enableHMAC && !globalHMACKey) {
353
- globalHMACKey = await generateHMACKey();
96
+ } else if (publicKeyPem instanceof CryptoJS__default.default.lib.WordArray) {
97
+ const base64Key = publicKeyPem.toString();
98
+ publicKeyString = base64ToPem(base64Key, "PUBLIC");
99
+ } else {
100
+ try {
101
+ const exported = await crypto.subtle.exportKey("spki", publicKeyPem);
102
+ const base64Key = base64Encode(exported);
103
+ publicKeyString = base64ToPem(base64Key, "PUBLIC");
104
+ } catch (error) {
105
+ throw new Error(
106
+ "Failed to export CryptoKey. In non-HTTPS environment, use string publicKey (Base64 or PEM) directly. " + (error instanceof Error ? error.message : String(error))
107
+ );
354
108
  }
355
- keyPairInitialized = true;
356
- keyUsageCount = 0;
357
- if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
358
- try {
359
- const publicKeyStr = await exportPublicKey(globalKeyPair.publicKey);
360
- if (initOptions.keyEncryptionPassword) {
361
- const privateKeyStr = await exportPrivateKey(globalKeyPair.privateKey);
362
- const salt = crypto.getRandomValues(new Uint8Array(16));
363
- const derivedKey = await deriveKeyFromPassword(
364
- initOptions.keyEncryptionPassword,
365
- salt.buffer,
366
- initOptions.pbkdf2Iterations
367
- );
368
- const { encrypted, iv } = await aesGCMEncrypt(privateKeyStr, derivedKey);
369
- const keyData = {
370
- encrypted: true,
371
- publicKey: publicKeyStr,
372
- privateKeyEncrypted: encrypted,
373
- iv,
374
- salt: base64Encode(salt.buffer),
375
- pbkdf2Iterations: initOptions.pbkdf2Iterations
376
- };
377
- window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
378
- if (!initOptions.isProduction && typeof console !== "undefined" && console.info) {
379
- console.info("\u2705 Keys encrypted and stored securely");
380
- }
381
- } else {
382
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
383
- console.warn(
384
- "\u26A0\uFE0F SECURITY WARNING: Storing private keys without encryption! Private keys will be stored in plain text (Base64 encoded). Provide keyEncryptionPassword for secure storage."
385
- );
386
- }
387
- const keyData = {
388
- publicKey: publicKeyStr,
389
- privateKey: await exportPrivateKey(globalKeyPair.privateKey)
390
- };
391
- window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
392
- }
393
- } catch (error) {
394
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
395
- console.error("Failed to persist keys");
396
- }
109
+ }
110
+ encrypt.setPublicKey(publicKeyString);
111
+ const MAX_ENCRYPT_LENGTH = 200;
112
+ if (plain.length > MAX_ENCRYPT_LENGTH) {
113
+ const chunks = [];
114
+ for (let i = 0; i < plain.length; i += MAX_ENCRYPT_LENGTH) {
115
+ const chunk = plain.slice(i, i + MAX_ENCRYPT_LENGTH);
116
+ const encrypted2 = encrypt.encrypt(chunk);
117
+ if (!encrypted2) {
118
+ throw new Error(
119
+ `RSA encryption failed for chunk ${i / MAX_ENCRYPT_LENGTH + 1}. Public key may be invalid or JSEncrypt may not be loaded correctly.`
120
+ );
397
121
  }
122
+ chunks.push(encrypted2);
398
123
  }
399
- } catch (error) {
400
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
401
- console.error("Failed to generate storage keys");
124
+ return chunks.join("|");
125
+ }
126
+ const encrypted = encrypt.encrypt(plain);
127
+ if (!encrypted) {
128
+ throw new Error(
129
+ `RSA encryption failed. Public key may be invalid or JSEncrypt may not be loaded correctly. Plain text length: ${plain.length} bytes.`
130
+ );
131
+ }
132
+ return encrypted;
133
+ } catch (error) {
134
+ if (error instanceof Error) {
135
+ if (error.message.includes("RSA encryption failed") || error.message.includes("Public key")) {
136
+ throw error;
402
137
  }
403
- throw error;
138
+ throw new Error(`[encryption] rsaEncrypt failed: ${error.message}`);
404
139
  }
405
- }
406
- if (initOptions.enableHMAC && !globalHMACKey) {
407
- globalHMACKey = await generateHMACKey();
140
+ throw new Error(`[encryption] rsaEncrypt failed: ${String(error)}`);
408
141
  }
409
142
  }
410
- function setStorageKeyPair(keyPair) {
411
- globalKeyPair = keyPair;
412
- keyPairInitialized = true;
413
- }
414
- function getStorageKeyPair() {
415
- return globalKeyPair;
416
- }
417
- function clearPersistedKeys() {
418
- if (typeof window !== "undefined" && window.localStorage && actualKeyStorageKey) {
143
+ async function rsaDecrypt(cipher, privateKeyPem) {
144
+ const decrypt = new JSEncrypt__default.default();
145
+ let privateKeyString;
146
+ if (typeof privateKeyPem === "string") {
147
+ if (privateKeyPem.includes("-----BEGIN")) {
148
+ privateKeyString = privateKeyPem.trim();
149
+ } else {
150
+ const trimmed = privateKeyPem.trim();
151
+ privateKeyString = base64ToPem(trimmed, "PRIVATE");
152
+ }
153
+ } else if (privateKeyPem instanceof CryptoJS__default.default.lib.WordArray) {
154
+ const base64Key = privateKeyPem.toString();
155
+ privateKeyString = base64ToPem(base64Key, "PRIVATE");
156
+ } else {
419
157
  try {
420
- window.localStorage.removeItem(actualKeyStorageKey);
421
- actualKeyStorageKey = null;
422
- keyPairInitialized = false;
423
- globalKeyPair = null;
424
- globalHMACKey = null;
425
- keyUsageCount = 0;
158
+ const exported = await crypto.subtle.exportKey("pkcs8", privateKeyPem);
159
+ const base64Key = base64Encode(exported);
160
+ privateKeyString = base64ToPem(base64Key, "PRIVATE");
426
161
  } catch (error) {
427
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
428
- console.error("Failed to clear persisted keys");
429
- }
430
- }
431
- }
432
- }
433
- function getKeyUsageCount() {
434
- return keyUsageCount;
435
- }
436
- function resetKeyUsageCount() {
437
- keyUsageCount = 0;
438
- }
439
- async function ensureKeyPair() {
440
- if (globalKeyPair) {
441
- keyUsageCount++;
442
- return;
443
- }
444
- if (!initOptions.autoGenerateKeys) {
445
- return;
446
- }
447
- if (initializationPromise) {
448
- await initializationPromise;
449
- if (globalKeyPair) {
450
- keyUsageCount++;
162
+ throw new Error(
163
+ "[encryption] rsaDecrypt: failed to export CryptoKey. In non-HTTPS environment, use PEM string directly."
164
+ );
451
165
  }
452
- return;
453
- }
454
- initializationPromise = initializeStorageKeys();
455
- try {
456
- await initializationPromise;
457
- } finally {
458
- initializationPromise = null;
459
166
  }
460
- if (globalKeyPair) {
461
- keyUsageCount++;
462
- }
463
- }
464
- function safeParseJSON(jsonStr, expectedType) {
465
- try {
466
- const parsed = JSON.parse(jsonStr);
467
- if (expectedType === "object" && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))) {
468
- throw new Error("Expected object but got different type");
469
- }
470
- if (expectedType === "array" && !Array.isArray(parsed)) {
471
- throw new Error("Expected array but got different type");
472
- }
473
- return parsed;
474
- } catch (error) {
475
- if (error instanceof SyntaxError) {
476
- throw new Error(`Invalid JSON format: ${error.message}`);
167
+ decrypt.setPrivateKey(privateKeyString);
168
+ const chunks = cipher.split("|");
169
+ const decryptedChunks = [];
170
+ for (const chunk of chunks) {
171
+ const decrypted = decrypt.decrypt(chunk);
172
+ if (!decrypted) {
173
+ throw new Error("[encryption] rsaDecrypt: RSA decryption failed");
477
174
  }
478
- throw error;
175
+ decryptedChunks.push(decrypted);
479
176
  }
177
+ return decryptedChunks.join("");
480
178
  }
481
- function validateTimestamp(timestamp, maxClockSkew = 5 * 60 * 1e3) {
482
- if (!initOptions.enableTimestampValidation || !timestamp) {
483
- return true;
484
- }
485
- if (initOptions.timestampMaxAge === 0) {
486
- return true;
487
- }
488
- const now = Date.now();
489
- const age = now - timestamp;
490
- const maxAge = initOptions.timestampMaxAge || 7 * 24 * 60 * 60 * 1e3;
491
- if (age < -maxClockSkew) {
492
- return false;
493
- }
494
- return age >= -maxClockSkew && age <= maxAge;
179
+ async function encryptWithEnvPublicKey(plain) {
180
+ const publicKey = getEnvPublicKey();
181
+ return rsaEncrypt(plain, publicKey);
495
182
  }
496
- async function encryptValue(value, publicKey, hmacKey) {
497
- const encryptedData = await rsaEncrypt(value, publicKey);
498
- if (hmacKey) {
499
- const hmac = await computeHMAC(encryptedData, hmacKey);
500
- const item = {
501
- data: encryptedData,
502
- hmac,
503
- encrypted: true,
504
- timestamp: Date.now()
505
- };
506
- return JSON.stringify(item);
507
- }
508
- return encryptedData;
183
+ async function decryptWithEnvPrivateKey(cipher) {
184
+ const privateKey = getEnvPrivateKey();
185
+ return rsaDecrypt(cipher, privateKey);
509
186
  }
510
- async function handleDecryptError(error, encryptedStr, key) {
511
- if (error instanceof Error && error.message.includes("HMAC verification failed")) {
512
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
513
- console.error(
514
- "\u26A0\uFE0F SECURITY ALERT: Data integrity check failed! Data may have been tampered with."
515
- );
187
+
188
+ // src/browser/SecureStorage/index.ts
189
+ var CONFIG = {
190
+ NAMESPACE: "sec_b_",
191
+ DEFAULT_EXPIRE: null
192
+ };
193
+ var SecureStorage = class _SecureStorage {
194
+ static get instances() {
195
+ if (!this._instances) {
196
+ this._instances = /* @__PURE__ */ new Map();
516
197
  }
517
- throw error;
518
- }
519
- if (error instanceof Error && error.message.includes("Data timestamp validation failed")) {
520
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
521
- console.warn("\u26A0\uFE0F SECURITY WARNING: Data timestamp validation failed");
198
+ return this._instances;
199
+ }
200
+ constructor(options) {
201
+ const storageType = options.storage === window.sessionStorage ? "session" : "local";
202
+ const namespace = options.namespace || CONFIG.NAMESPACE;
203
+ const instanceKey = `${storageType}_${namespace}`;
204
+ const existingInstance = _SecureStorage.instances.get(instanceKey);
205
+ if (existingInstance) {
206
+ return existingInstance;
522
207
  }
523
- throw error;
208
+ this.namespace = namespace;
209
+ this.storage = options.storage || window.localStorage;
210
+ this.defaultExpire = options.defaultExpire ?? CONFIG.DEFAULT_EXPIRE;
211
+ this.instanceKey = instanceKey;
212
+ _SecureStorage.instances.set(instanceKey, this);
524
213
  }
525
- try {
526
- const decryptedStr = base64Decode(encryptedStr);
527
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
528
- console.warn(
529
- `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}". This may be a security risk if sensitive data was stored without encryption.`
530
- );
531
- }
532
- return decryptedStr;
533
- } catch {
534
- throw error;
214
+ /**
215
+ * 获取单例实例(静态方法)
216
+ */
217
+ static getInstance(options) {
218
+ return new _SecureStorage(options);
535
219
  }
536
- }
537
- function handleNoKeyDecode(encryptedStr, key) {
538
- try {
539
- const decryptedStr = base64Decode(encryptedStr);
540
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
541
- console.warn(
542
- `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}" without encryption keys.`
543
- );
544
- }
545
- return decryptedStr;
546
- } catch (error) {
547
- throw new Error(`Failed to decode storage value for key "${key}"`);
220
+ /**
221
+ * 清除所有单例实例(用于测试或重置)
222
+ */
223
+ static clearInstances() {
224
+ _SecureStorage.instances.clear();
548
225
  }
549
- }
550
- async function decryptValue(encryptedValue, privateKey, hmacKey) {
551
- try {
552
- const item = JSON.parse(encryptedValue);
553
- if (item.encrypted && item.data && item.hmac) {
554
- if (hmacKey) {
555
- const isValid = await verifyHMAC(item.data, item.hmac, hmacKey);
556
- if (!isValid) {
557
- throw new Error("HMAC verification failed: data may have been tampered with");
558
- }
559
- }
560
- if (item.timestamp && !validateTimestamp(item.timestamp)) {
561
- throw new Error("Data timestamp validation failed: data may be expired or replayed");
562
- }
563
- return await rsaDecrypt(item.data, privateKey);
564
- }
565
- return await rsaDecrypt(encryptedValue, privateKey);
566
- } catch (error) {
567
- if (error instanceof Error && error.message.includes("HMAC verification failed")) {
568
- throw error;
569
- }
570
- throw new Error("Failed to decrypt storage value: invalid format or corrupted data");
226
+ /**
227
+ * 获取当前所有实例的数量(用于调试)
228
+ */
229
+ static getInstanceCount() {
230
+ return _SecureStorage.instances.size;
231
+ }
232
+ /**
233
+ * 获取完整键名(带命名空间)
234
+ */
235
+ _getFullKey(key) {
236
+ return `${this.namespace}${key}`;
237
+ }
238
+ /**
239
+ * 检查数据是否过期
240
+ */
241
+ _isExpired(expire) {
242
+ if (!expire) return false;
243
+ return Date.now() > expire;
571
244
  }
572
- }
573
- var localStorage = {
574
245
  /**
575
246
  * 设置值
576
- * @param key - 键
577
- * @param value - 值
578
- * @param options - 选项(过期时间、密钥等)
579
- * @returns Promise<void>
580
247
  */
581
- async set(key, value, options = {}) {
582
- if (typeof window === "undefined" || !window.localStorage) {
583
- throw new Error("localStorage is not available");
584
- }
585
- const { expiry, publicKey } = options;
586
- const item = {
587
- value,
588
- expiry: expiry ? Date.now() + expiry : void 0
589
- };
248
+ async set(key, value, expire = this.defaultExpire) {
590
249
  try {
591
- const jsonStr = JSON.stringify(item);
592
- await ensureKeyPair();
593
- const keyToUse = publicKey || globalKeyPair?.publicKey;
594
- if (keyToUse) {
595
- const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
596
- window.localStorage.setItem(key, encrypted);
597
- } else {
598
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
599
- console.warn(
600
- `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
601
- );
602
- }
603
- const encoded = base64Encode(jsonStr);
604
- window.localStorage.setItem(key, encoded);
605
- }
250
+ const fullKey = this._getFullKey(key);
251
+ const aesKey = generateRandomAESKeyString();
252
+ const storageData = {
253
+ value,
254
+ expire: expire ? Date.now() + expire : null,
255
+ timestamp: Date.now()
256
+ };
257
+ const encryptedData = encryptJsonWithAES(storageData, aesKey);
258
+ const encryptedKey = await encryptWithEnvPublicKey(aesKey);
259
+ const finalData = {
260
+ data: encryptedData,
261
+ key: encryptedKey,
262
+ version: "1.0"
263
+ };
264
+ this.storage.setItem(fullKey, JSON.stringify(finalData));
265
+ return true;
606
266
  } catch (error) {
607
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
608
- console.error("localStorage.set error:", error);
609
- }
610
- throw error;
267
+ console.error("[SecureStorage] \u4FDD\u5B58\u5931\u8D25:", error);
268
+ return false;
611
269
  }
612
- },
270
+ }
613
271
  /**
614
272
  * 获取值
615
- * @param key - 键
616
- * @param options - 选项(默认值、私钥等)
617
- * @returns Promise<T | undefined> 值或默认值
618
273
  */
619
- async get(key, options = {}) {
620
- if (typeof window === "undefined" || !window.localStorage) {
621
- return options.defaultValue;
622
- }
623
- const { defaultValue, privateKey } = options;
274
+ async get(key, defaultValue = null) {
624
275
  try {
625
- const encryptedStr = window.localStorage.getItem(key);
626
- if (!encryptedStr) return defaultValue;
627
- await ensureKeyPair();
628
- let decryptedStr;
629
- const keyToUse = privateKey || globalKeyPair?.privateKey;
630
- if (keyToUse) {
631
- try {
632
- decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
633
- } catch (error) {
634
- try {
635
- decryptedStr = await handleDecryptError(error, encryptedStr, key);
636
- } catch {
637
- return defaultValue;
638
- }
639
- }
640
- } else {
641
- try {
642
- decryptedStr = handleNoKeyDecode(encryptedStr, key);
643
- } catch {
644
- return defaultValue;
645
- }
276
+ const fullKey = this._getFullKey(key);
277
+ const storedData = this.storage.getItem(fullKey);
278
+ if (!storedData) {
279
+ return defaultValue;
646
280
  }
647
- const item = safeParseJSON(decryptedStr, "object");
648
- if (item.expiry && Date.now() > item.expiry) {
649
- window.localStorage.removeItem(key);
281
+ const finalData = JSON.parse(storedData);
282
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
283
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
284
+ if (this._isExpired(storageData.expire)) {
285
+ this.remove(key);
650
286
  return defaultValue;
651
287
  }
652
- return item.value;
288
+ return storageData.value;
653
289
  } catch (error) {
654
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
655
- console.warn(`Failed to parse storage item for key "${key}"`);
656
- }
290
+ console.error("[SecureStorage] \u8BFB\u53D6\u5931\u8D25:", error);
657
291
  return defaultValue;
658
292
  }
659
- },
293
+ }
660
294
  /**
661
- * 移除值
662
- * @param key - 键
295
+ * 删除值
663
296
  */
664
297
  remove(key) {
665
- if (typeof window === "undefined" || !window.localStorage) return;
666
298
  try {
667
- window.localStorage.removeItem(key);
299
+ const fullKey = this._getFullKey(key);
300
+ this.storage.removeItem(fullKey);
301
+ return true;
668
302
  } catch (error) {
669
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
670
- console.error("localStorage.remove error");
671
- }
303
+ console.error("[SecureStorage] \u79FB\u9664\u5931\u8D25:", error);
304
+ return false;
672
305
  }
673
- },
674
- /**
675
- * 清空所有值
676
- */
677
- clear() {
678
- if (typeof window === "undefined" || !window.localStorage) return;
679
- try {
680
- window.localStorage.clear();
681
- } catch (error) {
682
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
683
- console.error("localStorage.clear error");
684
- }
685
- }
686
- },
306
+ }
687
307
  /**
688
- * 获取所有键
689
- * @returns 键数组
308
+ * 检查键是否存在
690
309
  */
691
- keys() {
692
- if (typeof window === "undefined" || !window.localStorage) return [];
693
- const keys = [];
310
+ async has(key) {
694
311
  try {
695
- for (let i = 0; i < window.localStorage.length; i++) {
696
- const key = window.localStorage.key(i);
697
- if (key) keys.push(key);
312
+ const fullKey = this._getFullKey(key);
313
+ const storedData = this.storage.getItem(fullKey);
314
+ if (!storedData) return false;
315
+ const finalData = JSON.parse(storedData);
316
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
317
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
318
+ if (this._isExpired(storageData.expire)) {
319
+ this.remove(key);
320
+ return false;
698
321
  }
322
+ return true;
699
323
  } catch (error) {
700
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
701
- console.error("localStorage.keys error");
702
- }
324
+ return false;
703
325
  }
704
- return keys;
705
326
  }
706
- };
707
- var sessionStorage = {
708
327
  /**
709
- * 设置值
710
- * @param key - 键
711
- * @param value - 值
712
- * @param options - 选项(公钥等)
713
- * @returns Promise<void>
328
+ * 清空所有数据
714
329
  */
715
- async set(key, value, options = {}) {
716
- if (typeof window === "undefined" || !window.sessionStorage) {
717
- throw new Error("sessionStorage is not available");
718
- }
719
- const { publicKey } = options;
330
+ clear() {
720
331
  try {
721
- const jsonStr = JSON.stringify(value);
722
- await ensureKeyPair();
723
- const keyToUse = publicKey || globalKeyPair?.publicKey;
724
- if (keyToUse) {
725
- const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
726
- window.sessionStorage.setItem(key, encrypted);
727
- } else {
728
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
729
- console.warn(
730
- `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
731
- );
332
+ let count = 0;
333
+ const keys = [];
334
+ for (let i = 0; i < this.storage.length; i++) {
335
+ const key = this.storage.key(i);
336
+ if (key && key.startsWith(this.namespace)) {
337
+ keys.push(key);
732
338
  }
733
- const encoded = base64Encode(jsonStr);
734
- window.sessionStorage.setItem(key, encoded);
735
339
  }
340
+ keys.forEach((key) => {
341
+ this.storage.removeItem(key);
342
+ count++;
343
+ });
344
+ return count;
736
345
  } catch (error) {
737
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
738
- console.error("sessionStorage.set error:", error);
739
- }
740
- throw error;
346
+ console.error("[SecureStorage] \u6E05\u7A7A\u5931\u8D25:", error);
347
+ return 0;
741
348
  }
742
- },
349
+ }
743
350
  /**
744
- * 获取值
745
- * @param key - 键
746
- * @param options - 选项(默认值、私钥等)
747
- * @returns Promise<T | undefined> 值或默认值
351
+ * 获取所有键名
748
352
  */
749
- async get(key, options = {}) {
750
- if (typeof window === "undefined" || !window.sessionStorage) {
751
- return options.defaultValue;
752
- }
753
- const { defaultValue, privateKey } = options;
353
+ keys() {
754
354
  try {
755
- const encryptedStr = window.sessionStorage.getItem(key);
756
- if (!encryptedStr) return defaultValue;
757
- await ensureKeyPair();
758
- let decryptedStr;
759
- const keyToUse = privateKey || globalKeyPair?.privateKey;
760
- if (keyToUse) {
761
- try {
762
- decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
763
- } catch (error) {
764
- try {
765
- decryptedStr = await handleDecryptError(error, encryptedStr, key);
766
- } catch {
767
- return defaultValue;
768
- }
769
- }
770
- } else {
771
- try {
772
- decryptedStr = handleNoKeyDecode(encryptedStr, key);
773
- } catch {
774
- return defaultValue;
355
+ const keys = [];
356
+ for (let i = 0; i < this.storage.length; i++) {
357
+ const key = this.storage.key(i);
358
+ if (key && key.startsWith(this.namespace)) {
359
+ keys.push(key.substring(this.namespace.length));
775
360
  }
776
361
  }
777
- return safeParseJSON(decryptedStr);
778
- } catch {
779
- return defaultValue;
780
- }
781
- },
782
- /**
783
- * 移除值
784
- * @param key - 键
785
- */
786
- remove(key) {
787
- if (typeof window === "undefined" || !window.sessionStorage) return;
788
- try {
789
- window.sessionStorage.removeItem(key);
790
- } catch (error) {
791
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
792
- console.error("sessionStorage.remove error");
793
- }
794
- }
795
- },
796
- /**
797
- * 清空所有值
798
- */
799
- clear() {
800
- if (typeof window === "undefined" || !window.sessionStorage) return;
801
- try {
802
- window.sessionStorage.clear();
362
+ return keys;
803
363
  } catch (error) {
804
- if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
805
- console.error("sessionStorage.clear error");
806
- }
364
+ console.error("[SecureStorage] \u83B7\u53D6\u952E\u540D\u5931\u8D25:", error);
365
+ return [];
807
366
  }
808
367
  }
809
- };
810
- var cookie = {
811
- /**
812
- * 设置Cookie
813
- * @param key - 键
814
- * @param value - 值
815
- * @param options - Cookie选项
816
- */
817
- set(key, value, options = {}) {
818
- if (typeof document === "undefined") {
819
- throw new Error("document is not available");
820
- }
821
- let cookieStr = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
822
- if (options.expires) {
823
- const expiresDate = options.expires instanceof Date ? options.expires : new Date(Date.now() + options.expires * 24 * 60 * 60 * 1e3);
824
- cookieStr += `; expires=${expiresDate.toUTCString()}`;
825
- }
826
- if (options.path) cookieStr += `; path=${options.path}`;
827
- if (options.domain) cookieStr += `; domain=${options.domain}`;
828
- if (options.secure) cookieStr += "; secure";
829
- if (options.sameSite) cookieStr += `; sameSite=${options.sameSite}`;
830
- document.cookie = cookieStr;
831
- },
832
- /**
833
- * 获取Cookie
834
- * @param key - 键
835
- * @returns Cookie值
836
- */
837
- get(key) {
838
- if (typeof document === "undefined") return void 0;
839
- const name = encodeURIComponent(key);
840
- const cookies = document.cookie.split(";");
841
- for (const cookieStr of cookies) {
842
- const trimmed = cookieStr.trim();
843
- const eqIndex = trimmed.indexOf("=");
844
- if (eqIndex === -1) continue;
845
- const cookieKey = trimmed.substring(0, eqIndex).trim();
846
- const cookieValue = trimmed.substring(eqIndex + 1).trim();
847
- if (cookieKey === name) {
848
- const decoded = decodeURIComponent(cookieValue);
849
- return decoded === "" ? void 0 : decoded;
850
- }
851
- }
852
- return void 0;
853
- },
854
- /**
855
- * 移除Cookie
856
- * @param key - 键
857
- * @param options - Cookie选项
858
- */
859
- remove(key, options = {}) {
860
- cookie.set(key, "", {
861
- ...options,
862
- expires: /* @__PURE__ */ new Date(0)
863
- });
864
- },
865
368
  /**
866
- * 获取所有Cookie
867
- * @returns Cookie对象
369
+ * 获取数据条数
868
370
  */
869
- getAll() {
870
- if (typeof document === "undefined") return {};
871
- const cookies = {};
872
- document.cookie.split(";").forEach((cookieStr) => {
873
- const trimmed = cookieStr.trim();
874
- if (!trimmed) return;
875
- const eqIndex = trimmed.indexOf("=");
876
- if (eqIndex === -1) return;
877
- const key = trimmed.substring(0, eqIndex).trim();
878
- const value = trimmed.substring(eqIndex + 1).trim();
879
- if (key && value) {
880
- const decodedKey = decodeURIComponent(key);
881
- const decodedValue = decodeURIComponent(value);
882
- if (decodedValue !== "") {
883
- cookies[decodedKey] = decodedValue;
884
- }
885
- }
886
- });
887
- return cookies;
371
+ size() {
372
+ return this.keys().length;
888
373
  }
889
- };
890
- var secureStorage = {
891
374
  /**
892
- * 设置值(优先使用localStorage,失败则使用sessionStorage)
893
- * @param key - 键
894
- * @param value - 值
895
- * @param options - 选项(过期时间、公钥等)
896
- * @returns Promise<void>
375
+ * 清理过期数据
897
376
  */
898
- async set(key, value, options = {}) {
377
+ async clearExpired() {
899
378
  try {
900
- await localStorage.set(key, value, options);
901
- } catch {
902
- try {
903
- await sessionStorage.set(key, value, { publicKey: options.publicKey });
904
- } catch {
905
- if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
906
- console.warn("Both localStorage and sessionStorage are not available");
379
+ let count = 0;
380
+ const keys = this.keys();
381
+ for (const key of keys) {
382
+ const fullKey = this._getFullKey(key);
383
+ try {
384
+ const storedData = this.storage.getItem(fullKey);
385
+ if (storedData) {
386
+ const finalData = JSON.parse(storedData);
387
+ const aesKey = await decryptWithEnvPrivateKey(finalData.key);
388
+ const storageData = decryptJsonWithAES(finalData.data, aesKey);
389
+ if (this._isExpired(storageData.expire)) {
390
+ this.remove(key);
391
+ count++;
392
+ }
393
+ }
394
+ } catch (error) {
395
+ this.remove(key);
396
+ count++;
907
397
  }
908
398
  }
399
+ return count;
400
+ } catch (error) {
401
+ console.error("[SecureStorage] \u6E05\u7406\u8FC7\u671F\u6570\u636E\u5931\u8D25:", error);
402
+ return 0;
909
403
  }
910
- },
911
- /**
912
- * 获取值
913
- * @param key - 键
914
- * @param options - 选项(默认值、私钥等)
915
- * @returns Promise<T | undefined> 值或默认值
916
- */
917
- async get(key, options = {}) {
918
- const localValue = await localStorage.get(key, options);
919
- if (localValue !== void 0) return localValue;
920
- const sessionValue = await sessionStorage.get(key, options);
921
- return sessionValue !== void 0 ? sessionValue : options.defaultValue;
922
- },
923
- /**
924
- * 移除值
925
- * @param key - 键
926
- */
927
- remove(key) {
928
- localStorage.remove(key);
929
- sessionStorage.remove(key);
930
- },
404
+ }
931
405
  /**
932
- * 清空所有值
406
+ * 获取实例的唯一标识
933
407
  */
934
- clear() {
935
- localStorage.clear();
936
- sessionStorage.clear();
937
- },
408
+ getInstanceKey() {
409
+ return this.instanceKey;
410
+ }
938
411
  /**
939
- * 获取所有键名
940
- * @returns 键名数组
412
+ * 检查是否为单例实例
941
413
  */
942
- keys() {
943
- const localKeys = localStorage.keys();
944
- const sessionKeys = [];
945
- if (typeof window !== "undefined" && window.sessionStorage) {
946
- try {
947
- for (let i = 0; i < window.sessionStorage.length; i++) {
948
- const key = window.sessionStorage.key(i);
949
- if (key) sessionKeys.push(key);
950
- }
951
- } catch (error) {
952
- }
953
- }
954
- return Array.from(/* @__PURE__ */ new Set([...localKeys, ...sessionKeys]));
414
+ isSingleton() {
415
+ return _SecureStorage.instances.has(this.instanceKey);
955
416
  }
956
417
  };
418
+ var _defaultSecureStorage = null;
419
+ function _getDefaultSecureStorage() {
420
+ if (typeof window === "undefined") {
421
+ throw new Error("[SecureStorage] secureStorage is only available in browser environments.");
422
+ }
423
+ if (!_defaultSecureStorage) {
424
+ _defaultSecureStorage = new SecureStorage({});
425
+ }
426
+ return _defaultSecureStorage;
427
+ }
428
+ var secureStorage = new Proxy({}, {
429
+ get(_target, prop) {
430
+ const instance = _getDefaultSecureStorage();
431
+ const value = instance[prop];
432
+ if (typeof value === "function") {
433
+ return value.bind(instance);
434
+ }
435
+ return value;
436
+ }
437
+ });
438
+ var SecureStorage_default = SecureStorage;
957
439
 
958
- exports.clearPersistedKeys = clearPersistedKeys;
959
- exports.cookie = cookie;
960
- exports.getKeyUsageCount = getKeyUsageCount;
961
- exports.getStorageKeyPair = getStorageKeyPair;
962
- exports.initializeStorageKeys = initializeStorageKeys;
963
- exports.resetKeyUsageCount = resetKeyUsageCount;
440
+ exports.SecureStorage = SecureStorage;
441
+ exports.default = SecureStorage_default;
964
442
  exports.secureStorage = secureStorage;
965
- exports.setStorageKeyPair = setStorageKeyPair;