@alibarbar/common 1.1.2 → 1.1.4

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