@alibarbar/common 1.0.10 → 1.1.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.
Files changed (53) hide show
  1. package/dist/algorithm.cjs +1 -1
  2. package/dist/algorithm.js +1 -1
  3. package/dist/array.cjs +1 -1
  4. package/dist/array.js +1 -1
  5. package/dist/color.cjs +1 -1
  6. package/dist/color.js +1 -1
  7. package/dist/crypto.cjs +109 -1
  8. package/dist/crypto.d.mts +48 -1
  9. package/dist/crypto.d.ts +48 -1
  10. package/dist/crypto.js +104 -2
  11. package/dist/data-structure.cjs +1 -1
  12. package/dist/data-structure.js +1 -1
  13. package/dist/date.cjs +1 -1
  14. package/dist/date.js +1 -1
  15. package/dist/dom.cjs +1 -1
  16. package/dist/dom.js +1 -1
  17. package/dist/file.cjs +1 -1
  18. package/dist/file.js +1 -1
  19. package/dist/i18n.cjs +1 -1
  20. package/dist/i18n.js +1 -1
  21. package/dist/index.cjs +841 -430
  22. package/dist/index.d.mts +3 -3
  23. package/dist/index.d.ts +3 -3
  24. package/dist/index.js +832 -431
  25. package/dist/network.cjs +1 -1
  26. package/dist/network.js +1 -1
  27. package/dist/number.cjs +1 -1
  28. package/dist/number.js +1 -1
  29. package/dist/object.cjs +1 -1
  30. package/dist/object.js +1 -1
  31. package/dist/performance.cjs +1 -1
  32. package/dist/performance.js +1 -1
  33. package/dist/storage.cjs +481 -98
  34. package/dist/storage.d.mts +46 -1
  35. package/dist/storage.d.ts +46 -1
  36. package/dist/storage.js +478 -99
  37. package/dist/string.cjs +1 -1
  38. package/dist/string.js +1 -1
  39. package/dist/tracking.cjs +1 -1
  40. package/dist/tracking.js +1 -1
  41. package/dist/transform.cjs +1 -1
  42. package/dist/transform.js +1 -1
  43. package/dist/upload.cjs +2 -2
  44. package/dist/upload.d.mts +1 -1
  45. package/dist/upload.d.ts +1 -1
  46. package/dist/upload.js +2 -2
  47. package/dist/url.cjs +1 -1
  48. package/dist/url.js +1 -1
  49. package/dist/validation.cjs +1 -1
  50. package/dist/validation.js +1 -1
  51. package/package.json +1 -1
  52. /package/dist/{upload-DchqyDBQ.d.mts → index-DchqyDBQ.d.mts} +0 -0
  53. /package/dist/{upload-DchqyDBQ.d.ts → index-DchqyDBQ.d.ts} +0 -0
package/dist/storage.js CHANGED
@@ -1,36 +1,4 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropNames = Object.getOwnPropertyNames;
3
- var __esm = (fn, res) => function __init() {
4
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
- };
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
-
11
- // src/helper/crypto.ts
12
- var crypto_exports = {};
13
- __export(crypto_exports, {
14
- base64Decode: () => base64Decode,
15
- base64Encode: () => base64Encode,
16
- exportPrivateKey: () => exportPrivateKey,
17
- exportPublicKey: () => exportPublicKey,
18
- generateRSAKeyPair: () => generateRSAKeyPair,
19
- generateRandomString: () => generateRandomString,
20
- generateUUID: () => generateUUID,
21
- hash: () => hash,
22
- importPrivateKey: () => importPrivateKey,
23
- importPublicKey: () => importPublicKey,
24
- rsaDecrypt: () => rsaDecrypt,
25
- rsaEncrypt: () => rsaEncrypt,
26
- sha256: () => sha256
27
- });
28
- async function sha256(data) {
29
- const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
30
- const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
31
- const hashArray = Array.from(new Uint8Array(hashBuffer));
32
- return hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
33
- }
1
+ // src/helper/crypto/index.ts
34
2
  function base64Encode(data) {
35
3
  if (typeof data === "string") {
36
4
  return btoa(unescape(encodeURIComponent(data)));
@@ -49,16 +17,6 @@ function base64Decode(data) {
49
17
  throw new Error("Invalid Base64 string");
50
18
  }
51
19
  }
52
- function generateUUID() {
53
- if (typeof crypto !== "undefined" && crypto.randomUUID) {
54
- return crypto.randomUUID();
55
- }
56
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
57
- const r = Math.random() * 16 | 0;
58
- const v = c === "x" ? r : r & 3 | 8;
59
- return v.toString(16);
60
- });
61
- }
62
20
  function generateRandomString(length, charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") {
63
21
  let result = "";
64
22
  for (let i = 0; i < length; i++) {
@@ -66,15 +24,6 @@ function generateRandomString(length, charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcde
66
24
  }
67
25
  return result;
68
26
  }
69
- function hash(data) {
70
- let hashValue = 0;
71
- for (let i = 0; i < data.length; i++) {
72
- const char = data.charCodeAt(i);
73
- hashValue = (hashValue << 5) - hashValue + char;
74
- hashValue = hashValue & hashValue;
75
- }
76
- return Math.abs(hashValue);
77
- }
78
27
  async function generateRSAKeyPair(modulusLength = 2048) {
79
28
  if (typeof crypto === "undefined" || !crypto.subtle) {
80
29
  throw new Error("Web Crypto API is not available");
@@ -195,33 +144,428 @@ async function importPrivateKey(keyData) {
195
144
  ["decrypt"]
196
145
  );
197
146
  }
198
- var init_crypto = __esm({
199
- "src/helper/crypto.ts"() {
147
+ async function generateHMACKey() {
148
+ if (typeof crypto === "undefined" || !crypto.subtle) {
149
+ throw new Error("Web Crypto API is not available");
150
+ }
151
+ return crypto.subtle.generateKey(
152
+ {
153
+ name: "HMAC",
154
+ hash: "SHA-256"
155
+ },
156
+ true,
157
+ ["sign", "verify"]
158
+ );
159
+ }
160
+ async function computeHMAC(data, key) {
161
+ if (typeof crypto === "undefined" || !crypto.subtle) {
162
+ throw new Error("Web Crypto API is not available");
163
+ }
164
+ const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
165
+ const signature = await crypto.subtle.sign("HMAC", key, buffer);
166
+ return base64Encode(signature);
167
+ }
168
+ async function verifyHMAC(data, signature, key) {
169
+ if (typeof crypto === "undefined" || !crypto.subtle) {
170
+ throw new Error("Web Crypto API is not available");
171
+ }
172
+ try {
173
+ const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
174
+ const signatureBuffer = new Uint8Array(
175
+ atob(signature).split("").map((char) => char.charCodeAt(0))
176
+ );
177
+ return await crypto.subtle.verify("HMAC", key, signatureBuffer, dataBuffer);
178
+ } catch {
179
+ return false;
180
+ }
181
+ }
182
+ async function deriveKeyFromPassword(password, salt, iterations = 1e5, keyLength = 256) {
183
+ if (typeof crypto === "undefined" || !crypto.subtle) {
184
+ throw new Error("Web Crypto API is not available");
185
+ }
186
+ const saltBuffer = typeof salt === "string" ? new TextEncoder().encode(salt) : salt;
187
+ const passwordKey = await crypto.subtle.importKey(
188
+ "raw",
189
+ new TextEncoder().encode(password),
190
+ "PBKDF2",
191
+ false,
192
+ ["deriveBits", "deriveKey"]
193
+ );
194
+ return crypto.subtle.deriveKey(
195
+ {
196
+ name: "PBKDF2",
197
+ salt: saltBuffer,
198
+ iterations,
199
+ hash: "SHA-256"
200
+ },
201
+ passwordKey,
202
+ {
203
+ name: "AES-GCM",
204
+ length: keyLength
205
+ },
206
+ false,
207
+ ["encrypt", "decrypt"]
208
+ );
209
+ }
210
+ async function aesGCMEncrypt(data, key) {
211
+ if (typeof crypto === "undefined" || !crypto.subtle) {
212
+ throw new Error("Web Crypto API is not available");
200
213
  }
201
- });
214
+ const dataBuffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
215
+ const iv = crypto.getRandomValues(new Uint8Array(12));
216
+ const encrypted = await crypto.subtle.encrypt(
217
+ {
218
+ name: "AES-GCM",
219
+ iv
220
+ },
221
+ key,
222
+ dataBuffer
223
+ );
224
+ return {
225
+ encrypted: base64Encode(encrypted),
226
+ iv: base64Encode(iv.buffer)
227
+ };
228
+ }
229
+ async function aesGCMDecrypt(encryptedData, iv, key) {
230
+ if (typeof crypto === "undefined" || !crypto.subtle) {
231
+ throw new Error("Web Crypto API is not available");
232
+ }
233
+ const encryptedBuffer = new Uint8Array(
234
+ atob(encryptedData).split("").map((char) => char.charCodeAt(0))
235
+ );
236
+ const ivBuffer = new Uint8Array(
237
+ atob(iv).split("").map((char) => char.charCodeAt(0))
238
+ );
239
+ const decrypted = await crypto.subtle.decrypt(
240
+ {
241
+ name: "AES-GCM",
242
+ iv: ivBuffer
243
+ },
244
+ key,
245
+ encryptedBuffer
246
+ );
247
+ return new TextDecoder().decode(decrypted);
248
+ }
202
249
 
203
- // src/browser/storage.ts
204
- init_crypto();
250
+ // src/browser/SecureStorage/index.ts
205
251
  var globalKeyPair = null;
252
+ var globalHMACKey = null;
253
+ var keyPairInitialized = false;
254
+ var initOptions = {
255
+ autoGenerateKeys: true,
256
+ persistKeys: false,
257
+ keyStorageKey: void 0,
258
+ // 将自动生成随机键名
259
+ keyEncryptionPassword: void 0,
260
+ pbkdf2Iterations: 1e5,
261
+ keyModulusLength: 2048,
262
+ enableHMAC: true,
263
+ enableTimestampValidation: true,
264
+ timestampMaxAge: 7 * 24 * 60 * 60 * 1e3,
265
+ // 7 天
266
+ isProduction: false
267
+ };
268
+ var actualKeyStorageKey = null;
269
+ var keyUsageCount = 0;
270
+ var initializationPromise = null;
271
+ function generateKeyStorageKey() {
272
+ return `_sk_${generateRandomString(32)}_${Date.now()}`;
273
+ }
274
+ async function initializeStorageKeys(options = {}) {
275
+ if (options.forceReinitialize) {
276
+ globalKeyPair = null;
277
+ globalHMACKey = null;
278
+ keyPairInitialized = false;
279
+ actualKeyStorageKey = null;
280
+ keyUsageCount = 0;
281
+ initializationPromise = null;
282
+ } else if (keyPairInitialized && globalKeyPair) {
283
+ initOptions = { ...initOptions, ...options };
284
+ return;
285
+ }
286
+ initOptions = { ...initOptions, ...options };
287
+ if (initOptions.keyStorageKey) {
288
+ actualKeyStorageKey = initOptions.keyStorageKey;
289
+ } else {
290
+ actualKeyStorageKey = generateKeyStorageKey();
291
+ }
292
+ if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
293
+ try {
294
+ const storedKeys = window.localStorage.getItem(actualKeyStorageKey);
295
+ if (storedKeys) {
296
+ const keyData = JSON.parse(storedKeys);
297
+ if (keyData.encrypted && keyData.privateKeyEncrypted && keyData.salt) {
298
+ if (!initOptions.keyEncryptionPassword) {
299
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
300
+ console.error("Encrypted keys found but no password provided");
301
+ }
302
+ throw new Error("Password required to decrypt stored keys");
303
+ }
304
+ const saltArray = new Uint8Array(
305
+ atob(keyData.salt).split("").map((char) => char.charCodeAt(0))
306
+ );
307
+ const iterations = keyData.pbkdf2Iterations || initOptions.pbkdf2Iterations;
308
+ const derivedKey = await deriveKeyFromPassword(
309
+ initOptions.keyEncryptionPassword,
310
+ saltArray.buffer,
311
+ iterations
312
+ );
313
+ const decryptedPrivateKey = await aesGCMDecrypt(
314
+ keyData.privateKeyEncrypted,
315
+ keyData.iv,
316
+ derivedKey
317
+ );
318
+ globalKeyPair = {
319
+ publicKey: await importPublicKey(keyData.publicKey),
320
+ privateKey: await importPrivateKey(decryptedPrivateKey)
321
+ };
322
+ } else if (keyData.publicKey && keyData.privateKey) {
323
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
324
+ console.warn(
325
+ "\u26A0\uFE0F SECURITY WARNING: Loading unencrypted keys from storage. Consider re-initializing with password encryption."
326
+ );
327
+ }
328
+ globalKeyPair = {
329
+ publicKey: await importPublicKey(keyData.publicKey),
330
+ privateKey: await importPrivateKey(keyData.privateKey)
331
+ };
332
+ }
333
+ if (globalKeyPair) {
334
+ keyPairInitialized = true;
335
+ if (initOptions.enableHMAC && !globalHMACKey) {
336
+ globalHMACKey = await generateHMACKey();
337
+ }
338
+ return;
339
+ }
340
+ }
341
+ } catch (error) {
342
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
343
+ console.warn("Failed to load persisted keys, will generate new ones");
344
+ }
345
+ }
346
+ }
347
+ if (initOptions.autoGenerateKeys && !globalKeyPair) {
348
+ try {
349
+ globalKeyPair = await generateRSAKeyPair(initOptions.keyModulusLength);
350
+ if (initOptions.enableHMAC && !globalHMACKey) {
351
+ globalHMACKey = await generateHMACKey();
352
+ }
353
+ keyPairInitialized = true;
354
+ keyUsageCount = 0;
355
+ if (initOptions.persistKeys && typeof window !== "undefined" && window.localStorage) {
356
+ try {
357
+ const publicKeyStr = await exportPublicKey(globalKeyPair.publicKey);
358
+ if (initOptions.keyEncryptionPassword) {
359
+ const privateKeyStr = await exportPrivateKey(globalKeyPair.privateKey);
360
+ const salt = crypto.getRandomValues(new Uint8Array(16));
361
+ const derivedKey = await deriveKeyFromPassword(
362
+ initOptions.keyEncryptionPassword,
363
+ salt.buffer,
364
+ initOptions.pbkdf2Iterations
365
+ );
366
+ const { encrypted, iv } = await aesGCMEncrypt(privateKeyStr, derivedKey);
367
+ const keyData = {
368
+ encrypted: true,
369
+ publicKey: publicKeyStr,
370
+ privateKeyEncrypted: encrypted,
371
+ iv,
372
+ salt: base64Encode(salt.buffer),
373
+ pbkdf2Iterations: initOptions.pbkdf2Iterations
374
+ };
375
+ window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
376
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.info) {
377
+ console.info("\u2705 Keys encrypted and stored securely");
378
+ }
379
+ } else {
380
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
381
+ console.warn(
382
+ "\u26A0\uFE0F SECURITY WARNING: Storing private keys without encryption! Private keys will be stored in plain text (Base64 encoded). Provide keyEncryptionPassword for secure storage."
383
+ );
384
+ }
385
+ const keyData = {
386
+ publicKey: publicKeyStr,
387
+ privateKey: await exportPrivateKey(globalKeyPair.privateKey)
388
+ };
389
+ window.localStorage.setItem(actualKeyStorageKey, JSON.stringify(keyData));
390
+ }
391
+ } catch (error) {
392
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
393
+ console.error("Failed to persist keys");
394
+ }
395
+ }
396
+ }
397
+ } catch (error) {
398
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
399
+ console.error("Failed to generate storage keys");
400
+ }
401
+ throw error;
402
+ }
403
+ }
404
+ if (initOptions.enableHMAC && !globalHMACKey) {
405
+ globalHMACKey = await generateHMACKey();
406
+ }
407
+ }
206
408
  function setStorageKeyPair(keyPair) {
207
409
  globalKeyPair = keyPair;
410
+ keyPairInitialized = true;
208
411
  }
209
412
  function getStorageKeyPair() {
210
413
  return globalKeyPair;
211
414
  }
212
- async function encryptValue(value, publicKey) {
213
- return rsaEncrypt(value, publicKey);
415
+ function clearPersistedKeys() {
416
+ if (typeof window !== "undefined" && window.localStorage && actualKeyStorageKey) {
417
+ try {
418
+ window.localStorage.removeItem(actualKeyStorageKey);
419
+ actualKeyStorageKey = null;
420
+ keyPairInitialized = false;
421
+ globalKeyPair = null;
422
+ globalHMACKey = null;
423
+ keyUsageCount = 0;
424
+ } catch (error) {
425
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
426
+ console.error("Failed to clear persisted keys");
427
+ }
428
+ }
429
+ }
430
+ }
431
+ function getKeyUsageCount() {
432
+ return keyUsageCount;
433
+ }
434
+ function resetKeyUsageCount() {
435
+ keyUsageCount = 0;
436
+ }
437
+ async function ensureKeyPair() {
438
+ if (globalKeyPair) {
439
+ keyUsageCount++;
440
+ return;
441
+ }
442
+ if (!initOptions.autoGenerateKeys) {
443
+ return;
444
+ }
445
+ if (initializationPromise) {
446
+ await initializationPromise;
447
+ if (globalKeyPair) {
448
+ keyUsageCount++;
449
+ }
450
+ return;
451
+ }
452
+ initializationPromise = initializeStorageKeys();
453
+ try {
454
+ await initializationPromise;
455
+ } finally {
456
+ initializationPromise = null;
457
+ }
458
+ if (globalKeyPair) {
459
+ keyUsageCount++;
460
+ }
214
461
  }
215
- async function decryptValue(encryptedValue, privateKey) {
462
+ function safeParseJSON(jsonStr, expectedType) {
216
463
  try {
217
- return await rsaDecrypt(encryptedValue, privateKey);
464
+ const parsed = JSON.parse(jsonStr);
465
+ if (expectedType === "object" && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))) {
466
+ throw new Error("Expected object but got different type");
467
+ }
468
+ if (expectedType === "array" && !Array.isArray(parsed)) {
469
+ throw new Error("Expected array but got different type");
470
+ }
471
+ return parsed;
472
+ } catch (error) {
473
+ if (error instanceof SyntaxError) {
474
+ throw new Error(`Invalid JSON format: ${error.message}`);
475
+ }
476
+ throw error;
477
+ }
478
+ }
479
+ function validateTimestamp(timestamp, maxClockSkew = 5 * 60 * 1e3) {
480
+ if (!initOptions.enableTimestampValidation || !timestamp) {
481
+ return true;
482
+ }
483
+ if (initOptions.timestampMaxAge === 0) {
484
+ return true;
485
+ }
486
+ const now = Date.now();
487
+ const age = now - timestamp;
488
+ const maxAge = initOptions.timestampMaxAge || 7 * 24 * 60 * 60 * 1e3;
489
+ if (age < -maxClockSkew) {
490
+ return false;
491
+ }
492
+ return age >= -maxClockSkew && age <= maxAge;
493
+ }
494
+ async function encryptValue(value, publicKey, hmacKey) {
495
+ const encryptedData = await rsaEncrypt(value, publicKey);
496
+ if (hmacKey) {
497
+ const hmac = await computeHMAC(encryptedData, hmacKey);
498
+ const item = {
499
+ data: encryptedData,
500
+ hmac,
501
+ encrypted: true,
502
+ timestamp: Date.now()
503
+ };
504
+ return JSON.stringify(item);
505
+ }
506
+ return encryptedData;
507
+ }
508
+ async function handleDecryptError(error, encryptedStr, key) {
509
+ if (error instanceof Error && error.message.includes("HMAC verification failed")) {
510
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
511
+ console.error(
512
+ "\u26A0\uFE0F SECURITY ALERT: Data integrity check failed! Data may have been tampered with."
513
+ );
514
+ }
515
+ throw error;
516
+ }
517
+ if (error instanceof Error && error.message.includes("Data timestamp validation failed")) {
518
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
519
+ console.warn("\u26A0\uFE0F SECURITY WARNING: Data timestamp validation failed");
520
+ }
521
+ throw error;
522
+ }
523
+ try {
524
+ const decryptedStr = base64Decode(encryptedStr);
525
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
526
+ console.warn(
527
+ `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}". This may be a security risk if sensitive data was stored without encryption.`
528
+ );
529
+ }
530
+ return decryptedStr;
218
531
  } catch {
219
- try {
220
- JSON.parse(encryptedValue);
221
- return encryptedValue;
222
- } catch {
223
- throw new Error("Failed to decrypt storage value");
532
+ throw error;
533
+ }
534
+ }
535
+ function handleNoKeyDecode(encryptedStr, key) {
536
+ try {
537
+ const decryptedStr = base64Decode(encryptedStr);
538
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
539
+ console.warn(
540
+ `\u26A0\uFE0F SECURITY WARNING: Reading unencrypted data for key "${key}" without encryption keys.`
541
+ );
542
+ }
543
+ return decryptedStr;
544
+ } catch (error) {
545
+ throw new Error(`Failed to decode storage value for key "${key}"`);
546
+ }
547
+ }
548
+ async function decryptValue(encryptedValue, privateKey, hmacKey) {
549
+ try {
550
+ const item = JSON.parse(encryptedValue);
551
+ if (item.encrypted && item.data && item.hmac) {
552
+ if (hmacKey) {
553
+ const isValid = await verifyHMAC(item.data, item.hmac, hmacKey);
554
+ if (!isValid) {
555
+ throw new Error("HMAC verification failed: data may have been tampered with");
556
+ }
557
+ }
558
+ if (item.timestamp && !validateTimestamp(item.timestamp)) {
559
+ throw new Error("Data timestamp validation failed: data may be expired or replayed");
560
+ }
561
+ return await rsaDecrypt(item.data, privateKey);
224
562
  }
563
+ return await rsaDecrypt(encryptedValue, privateKey);
564
+ } catch (error) {
565
+ if (error instanceof Error && error.message.includes("HMAC verification failed")) {
566
+ throw error;
567
+ }
568
+ throw new Error("Failed to decrypt storage value: invalid format or corrupted data");
225
569
  }
226
570
  }
227
571
  var localStorage = {
@@ -243,17 +587,24 @@ var localStorage = {
243
587
  };
244
588
  try {
245
589
  const jsonStr = JSON.stringify(item);
590
+ await ensureKeyPair();
246
591
  const keyToUse = publicKey || globalKeyPair?.publicKey;
247
592
  if (keyToUse) {
248
- const encrypted = await encryptValue(jsonStr, keyToUse);
593
+ const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
249
594
  window.localStorage.setItem(key, encrypted);
250
595
  } else {
251
- const { base64Encode: base64Encode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
252
- const encoded = base64Encode2(jsonStr);
596
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
597
+ console.warn(
598
+ `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
599
+ );
600
+ }
601
+ const encoded = base64Encode(jsonStr);
253
602
  window.localStorage.setItem(key, encoded);
254
603
  }
255
604
  } catch (error) {
256
- console.error("localStorage.set error:", error);
605
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
606
+ console.error("localStorage.set error:", error);
607
+ }
257
608
  throw error;
258
609
  }
259
610
  },
@@ -271,34 +622,36 @@ var localStorage = {
271
622
  try {
272
623
  const encryptedStr = window.localStorage.getItem(key);
273
624
  if (!encryptedStr) return defaultValue;
625
+ await ensureKeyPair();
274
626
  let decryptedStr;
275
627
  const keyToUse = privateKey || globalKeyPair?.privateKey;
276
628
  if (keyToUse) {
277
629
  try {
278
- decryptedStr = await decryptValue(encryptedStr, keyToUse);
279
- } catch {
280
- const { base64Decode: base64Decode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
630
+ decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
631
+ } catch (error) {
281
632
  try {
282
- decryptedStr = base64Decode2(encryptedStr);
633
+ decryptedStr = await handleDecryptError(error, encryptedStr, key);
283
634
  } catch {
284
635
  return defaultValue;
285
636
  }
286
637
  }
287
638
  } else {
288
- const { base64Decode: base64Decode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
289
639
  try {
290
- decryptedStr = base64Decode2(encryptedStr);
640
+ decryptedStr = handleNoKeyDecode(encryptedStr, key);
291
641
  } catch {
292
642
  return defaultValue;
293
643
  }
294
644
  }
295
- const item = JSON.parse(decryptedStr);
645
+ const item = safeParseJSON(decryptedStr, "object");
296
646
  if (item.expiry && Date.now() > item.expiry) {
297
647
  window.localStorage.removeItem(key);
298
648
  return defaultValue;
299
649
  }
300
650
  return item.value;
301
- } catch {
651
+ } catch (error) {
652
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
653
+ console.warn(`Failed to parse storage item for key "${key}"`);
654
+ }
302
655
  return defaultValue;
303
656
  }
304
657
  },
@@ -311,7 +664,9 @@ var localStorage = {
311
664
  try {
312
665
  window.localStorage.removeItem(key);
313
666
  } catch (error) {
314
- console.error("localStorage.remove error:", error);
667
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
668
+ console.error("localStorage.remove error");
669
+ }
315
670
  }
316
671
  },
317
672
  /**
@@ -322,7 +677,9 @@ var localStorage = {
322
677
  try {
323
678
  window.localStorage.clear();
324
679
  } catch (error) {
325
- console.error("localStorage.clear error:", error);
680
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
681
+ console.error("localStorage.clear error");
682
+ }
326
683
  }
327
684
  },
328
685
  /**
@@ -338,7 +695,9 @@ var localStorage = {
338
695
  if (key) keys.push(key);
339
696
  }
340
697
  } catch (error) {
341
- console.error("localStorage.keys error:", error);
698
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
699
+ console.error("localStorage.keys error");
700
+ }
342
701
  }
343
702
  return keys;
344
703
  }
@@ -358,17 +717,24 @@ var sessionStorage = {
358
717
  const { publicKey } = options;
359
718
  try {
360
719
  const jsonStr = JSON.stringify(value);
720
+ await ensureKeyPair();
361
721
  const keyToUse = publicKey || globalKeyPair?.publicKey;
362
722
  if (keyToUse) {
363
- const encrypted = await encryptValue(jsonStr, keyToUse);
723
+ const encrypted = await encryptValue(jsonStr, keyToUse, globalHMACKey);
364
724
  window.sessionStorage.setItem(key, encrypted);
365
725
  } else {
366
- const { base64Encode: base64Encode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
367
- const encoded = base64Encode2(jsonStr);
726
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
727
+ console.warn(
728
+ `\u26A0\uFE0F SECURITY WARNING: Storing data without encryption for key "${key}". Data is only Base64 encoded, not encrypted!`
729
+ );
730
+ }
731
+ const encoded = base64Encode(jsonStr);
368
732
  window.sessionStorage.setItem(key, encoded);
369
733
  }
370
734
  } catch (error) {
371
- console.error("sessionStorage.set error:", error);
735
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
736
+ console.error("sessionStorage.set error:", error);
737
+ }
372
738
  throw error;
373
739
  }
374
740
  },
@@ -386,28 +752,27 @@ var sessionStorage = {
386
752
  try {
387
753
  const encryptedStr = window.sessionStorage.getItem(key);
388
754
  if (!encryptedStr) return defaultValue;
755
+ await ensureKeyPair();
389
756
  let decryptedStr;
390
757
  const keyToUse = privateKey || globalKeyPair?.privateKey;
391
758
  if (keyToUse) {
392
759
  try {
393
- decryptedStr = await decryptValue(encryptedStr, keyToUse);
394
- } catch {
395
- const { base64Decode: base64Decode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
760
+ decryptedStr = await decryptValue(encryptedStr, keyToUse, globalHMACKey);
761
+ } catch (error) {
396
762
  try {
397
- decryptedStr = base64Decode2(encryptedStr);
763
+ decryptedStr = await handleDecryptError(error, encryptedStr, key);
398
764
  } catch {
399
765
  return defaultValue;
400
766
  }
401
767
  }
402
768
  } else {
403
- const { base64Decode: base64Decode2 } = await Promise.resolve().then(() => (init_crypto(), crypto_exports));
404
769
  try {
405
- decryptedStr = base64Decode2(encryptedStr);
770
+ decryptedStr = handleNoKeyDecode(encryptedStr, key);
406
771
  } catch {
407
772
  return defaultValue;
408
773
  }
409
774
  }
410
- return JSON.parse(decryptedStr);
775
+ return safeParseJSON(decryptedStr);
411
776
  } catch {
412
777
  return defaultValue;
413
778
  }
@@ -421,7 +786,9 @@ var sessionStorage = {
421
786
  try {
422
787
  window.sessionStorage.removeItem(key);
423
788
  } catch (error) {
424
- console.error("sessionStorage.remove error:", error);
789
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
790
+ console.error("sessionStorage.remove error");
791
+ }
425
792
  }
426
793
  },
427
794
  /**
@@ -432,7 +799,9 @@ var sessionStorage = {
432
799
  try {
433
800
  window.sessionStorage.clear();
434
801
  } catch (error) {
435
- console.error("sessionStorage.clear error:", error);
802
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.error) {
803
+ console.error("sessionStorage.clear error");
804
+ }
436
805
  }
437
806
  }
438
807
  };
@@ -467,8 +836,12 @@ var cookie = {
467
836
  if (typeof document === "undefined") return void 0;
468
837
  const name = encodeURIComponent(key);
469
838
  const cookies = document.cookie.split(";");
470
- for (const cookie2 of cookies) {
471
- const [cookieKey, cookieValue] = cookie2.trim().split("=");
839
+ for (const cookieStr of cookies) {
840
+ const trimmed = cookieStr.trim();
841
+ const eqIndex = trimmed.indexOf("=");
842
+ if (eqIndex === -1) continue;
843
+ const cookieKey = trimmed.substring(0, eqIndex).trim();
844
+ const cookieValue = trimmed.substring(eqIndex + 1).trim();
472
845
  if (cookieKey === name) {
473
846
  return decodeURIComponent(cookieValue);
474
847
  }
@@ -494,7 +867,11 @@ var cookie = {
494
867
  if (typeof document === "undefined") return {};
495
868
  const cookies = {};
496
869
  document.cookie.split(";").forEach((cookieStr) => {
497
- const [key, value] = cookieStr.trim().split("=");
870
+ const trimmed = cookieStr.trim();
871
+ const eqIndex = trimmed.indexOf("=");
872
+ if (eqIndex === -1) return;
873
+ const key = trimmed.substring(0, eqIndex).trim();
874
+ const value = trimmed.substring(eqIndex + 1).trim();
498
875
  if (key && value) {
499
876
  cookies[decodeURIComponent(key)] = decodeURIComponent(value);
500
877
  }
@@ -517,7 +894,9 @@ var storage = {
517
894
  try {
518
895
  await sessionStorage.set(key, value, { publicKey: options.publicKey });
519
896
  } catch {
520
- console.warn("Both localStorage and sessionStorage are not available");
897
+ if (!initOptions.isProduction && typeof console !== "undefined" && console.warn) {
898
+ console.warn("Both localStorage and sessionStorage are not available");
899
+ }
521
900
  }
522
901
  }
523
902
  },
@@ -550,4 +929,4 @@ var storage = {
550
929
  }
551
930
  };
552
931
 
553
- export { cookie, getStorageKeyPair, localStorage, sessionStorage, setStorageKeyPair, storage };
932
+ export { clearPersistedKeys, cookie, getKeyUsageCount, getStorageKeyPair, initializeStorageKeys, localStorage, resetKeyUsageCount, sessionStorage, setStorageKeyPair, storage };