{"version":3,"file":"secure-storage.mjs","sources":["../../../src/lib/security/secure-storage.ts"],"sourcesContent":["/**\n * @fileoverview Secure Storage with Encryption\n * @module @/lib/security/secure-storage\n *\n * Provides encrypted localStorage and sessionStorage wrappers for the\n * Harbor React Framework. Uses Web Crypto API for AES-GCM encryption\n * with PBKDF2 key derivation.\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API\n * @see https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto\n *\n * @author Harbor Security Team\n * @version 1.0.0\n */\n\nimport type {\n  SecureStorageConfig,\n  SecureStorageInterface,\n  SecureStorageResult,\n  SecureStorageSetOptions,\n  SecureStorageMetadata,\n  StorageQuotaInfo,\n  EncryptedData,\n  EncryptionAlgorithm,\n  EncryptedString,\n} from './types';\nimport { secureStorageConfig } from '@/config/security.config';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/**\n * Current encryption schema version\n */\nconst ENCRYPTION_VERSION = 1;\n\n/**\n * Metadata storage key prefix\n */\nconst METADATA_PREFIX = '__meta_';\n\n/**\n * Key cache storage\n */\ninterface CachedKey {\n  key: CryptoKey;\n  createdAt: number;\n}\n\nconst keyCache = new Map<string, CachedKey>();\n\n// ============================================================================\n// Cryptographic Utilities\n// ============================================================================\n\n/**\n * Generate cryptographically secure random bytes\n */\nfunction getRandomBytes(length: number): Uint8Array {\n  const bytes = new Uint8Array(length);\n  crypto.getRandomValues(bytes);\n  return bytes;\n}\n\n/**\n * Convert bytes to base64 string\n */\nfunction bytesToBase64(bytes: Uint8Array): string {\n  const binString = Array.from(bytes, (byte) => String.fromCharCode(byte)).join('');\n  return btoa(binString);\n}\n\n/**\n * Convert base64 string to bytes\n */\nfunction base64ToBytes(base64: string): Uint8Array {\n  const binString = atob(base64);\n  return Uint8Array.from(binString, (char) => char.charCodeAt(0));\n}\n\n/**\n * Compute SHA-256 hash\n */\nasync function sha256(data: string): Promise<string> {\n  const encoder = new TextEncoder();\n  const bytes = encoder.encode(data);\n  const hashBuffer = await crypto.subtle.digest('SHA-256', bytes);\n  return bytesToBase64(new Uint8Array(hashBuffer));\n}\n\n/**\n * Derive an encryption key using PBKDF2\n */\nasync function deriveKey(\n  password: string,\n  salt: Uint8Array,\n  config: SecureStorageConfig\n): Promise<CryptoKey> {\n  const encoder = new TextEncoder();\n  const keyMaterial = await crypto.subtle.importKey(\n    'raw',\n    encoder.encode(password),\n    'PBKDF2',\n    false,\n    ['deriveKey']\n  );\n\n  const algorithm: Pbkdf2Params = {\n    name: 'PBKDF2',\n    salt: salt as BufferSource,\n    iterations: config.iterations,\n    hash: 'SHA-256',\n  };\n\n  const derivedKeyAlgorithm: AesKeyGenParams = {\n    name: config.algorithm,\n    length: config.keyLength,\n  };\n\n  return crypto.subtle.deriveKey(algorithm, keyMaterial, derivedKeyAlgorithm, false, [\n    'encrypt',\n    'decrypt',\n  ]);\n}\n\n/**\n * Get or create cached encryption key\n */\nasync function getCachedKey(\n  password: string,\n  salt: Uint8Array,\n  config: SecureStorageConfig\n): Promise<CryptoKey> {\n  const cacheKey = `${password}:${bytesToBase64(salt)}`;\n  const cached = keyCache.get(cacheKey);\n\n  if (cached) {\n    const age = Date.now() - cached.createdAt;\n    if (age < config.keyTtl) {\n      return cached.key;\n    }\n    keyCache.delete(cacheKey);\n  }\n\n  const key = await deriveKey(password, salt, config);\n  keyCache.set(cacheKey, { key, createdAt: Date.now() });\n\n  return key;\n}\n\n/**\n * Clear expired keys from cache\n */\nfunction clearExpiredKeys(ttl: number): void {\n  const now = Date.now();\n  for (const [cacheKey, cached] of keyCache.entries()) {\n    if (now - cached.createdAt >= ttl) {\n      keyCache.delete(cacheKey);\n    }\n  }\n}\n\n// ============================================================================\n// Compression Utilities\n// ============================================================================\n\n/**\n * Compress a string using CompressionStream API\n */\nasync function compress(data: string): Promise<Uint8Array> {\n  const encoder = new TextEncoder();\n  const bytes = encoder.encode(data);\n\n  // Check for CompressionStream support\n  if (typeof CompressionStream === 'undefined') {\n    // Fallback: no compression\n    return bytes;\n  }\n\n  const stream = new CompressionStream('gzip');\n  const writer = stream.writable.getWriter();\n  const reader = stream.readable.getReader();\n\n  void writer.write(bytes);\n  void writer.close();\n\n  const chunks: Uint8Array[] = [];\n  let result = await reader.read();\n\n  while (!result.done) {\n    chunks.push(result.value);\n    result = await reader.read();\n  }\n\n  // Concatenate chunks\n  const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n  const compressed = new Uint8Array(totalLength);\n  let offset = 0;\n\n  for (const chunk of chunks) {\n    compressed.set(chunk, offset);\n    offset += chunk.length;\n  }\n\n  return compressed;\n}\n\n/**\n * Decompress a string using DecompressionStream API\n */\nasync function decompress(data: Uint8Array): Promise<string> {\n  // Check for DecompressionStream support\n  if (typeof DecompressionStream === 'undefined') {\n    // Fallback: assume not compressed\n    const decoder = new TextDecoder();\n    return decoder.decode(data);\n  }\n\n  const stream = new DecompressionStream('gzip');\n  const writer = stream.writable.getWriter();\n  const reader = stream.readable.getReader();\n\n  void writer.write(data as BufferSource | undefined);\n  void writer.close();\n\n  const chunks: Uint8Array[] = [];\n  let result = await reader.read();\n\n  while (!result.done) {\n    chunks.push(result.value);\n    result = await reader.read();\n  }\n\n  // Concatenate and decode\n  const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n  const decompressed = new Uint8Array(totalLength);\n  let offset = 0;\n\n  for (const chunk of chunks) {\n    decompressed.set(chunk, offset);\n    offset += chunk.length;\n  }\n\n  const decoder = new TextDecoder();\n  return decoder.decode(decompressed);\n}\n\n// ============================================================================\n// Encryption/Decryption\n// ============================================================================\n\n/**\n * Encrypt data using AES-GCM\n */\nasync function encrypt(\n  data: string,\n  password: string,\n  config: SecureStorageConfig\n): Promise<EncryptedData> {\n  const salt = getRandomBytes(config.saltLength);\n  const iv = getRandomBytes(config.ivLength);\n  const key = await getCachedKey(password, salt, config);\n\n  // Optionally compress\n  let dataBytes: Uint8Array;\n  if (config.compress) {\n    dataBytes = await compress(data);\n  } else {\n    const encoder = new TextEncoder();\n    dataBytes = encoder.encode(data);\n  }\n\n  // Encrypt\n  const algorithm: AesGcmParams = {\n    name: config.algorithm,\n    iv: iv as BufferSource,\n    tagLength: 128,\n  };\n\n  const encrypted = await crypto.subtle.encrypt(algorithm, key, dataBytes as BufferSource);\n  const encryptedBytes = new Uint8Array(encrypted);\n\n  // For AES-GCM, the auth tag is appended to the ciphertext\n  // Extract it for separate storage (last 16 bytes)\n  const ciphertext = encryptedBytes.slice(0, -16);\n  const tag = encryptedBytes.slice(-16);\n\n  // Compute checksum for integrity verification\n  const checksum = await sha256(bytesToBase64(encryptedBytes));\n\n  return {\n    version: ENCRYPTION_VERSION,\n    algorithm: config.algorithm,\n    salt: bytesToBase64(salt),\n    iv: bytesToBase64(iv),\n    data: bytesToBase64(ciphertext),\n    tag: bytesToBase64(tag),\n    encryptedAt: Date.now(),\n    checksum,\n  };\n}\n\n/**\n * Decrypt data using AES-GCM\n */\nasync function decrypt(\n  encryptedData: EncryptedData,\n  password: string,\n  config: SecureStorageConfig\n): Promise<string> {\n  // Verify version\n  if (encryptedData.version !== ENCRYPTION_VERSION) {\n    throw new Error(`Unsupported encryption version: ${encryptedData.version}`);\n  }\n\n  const salt = base64ToBytes(encryptedData.salt);\n  const iv = base64ToBytes(encryptedData.iv);\n  const ciphertext = base64ToBytes(encryptedData.data);\n  const tag =\n    encryptedData.tag !== null && encryptedData.tag !== undefined && encryptedData.tag !== ''\n      ? base64ToBytes(encryptedData.tag)\n      : new Uint8Array(0);\n\n  // Reconstruct the encrypted data with tag\n  const encryptedBytes = new Uint8Array(ciphertext.length + tag.length);\n  encryptedBytes.set(ciphertext);\n  encryptedBytes.set(tag, ciphertext.length);\n\n  // Verify checksum\n  const checksum = await sha256(bytesToBase64(encryptedBytes));\n  if (checksum !== encryptedData.checksum) {\n    throw new Error('Data integrity check failed');\n  }\n\n  const key = await getCachedKey(password, salt, config);\n\n  // Decrypt\n  const algorithm: AesGcmParams = {\n    name: config.algorithm as 'AES-GCM',\n    iv: iv as BufferSource,\n    tagLength: 128,\n  };\n\n  const decrypted = await crypto.subtle.decrypt(algorithm, key, encryptedBytes);\n  const decryptedBytes = new Uint8Array(decrypted);\n\n  // Optionally decompress\n  if (config.compress) {\n    return decompress(decryptedBytes);\n  }\n\n  const decoder = new TextDecoder();\n  return decoder.decode(decryptedBytes);\n}\n\n// ============================================================================\n// Secure Storage Class\n// ============================================================================\n\n/**\n * Secure Storage implementation with encryption\n *\n * Features:\n * - AES-GCM encryption with PBKDF2 key derivation\n * - Optional compression for large data\n * - Automatic expiration handling\n * - Storage quota monitoring\n * - IndexedDB fallback for large items\n *\n * @example\n * ```typescript\n * const storage = new SecureStorage('my-secret-key');\n *\n * // Store encrypted data\n * await storage.setItem('user-data', { name: 'John', email: 'john@example.com' });\n *\n * // Retrieve decrypted data\n * const result = await storage.getItem<{ name: string; email: string }>('user-data');\n * if (result.success) {\n *   console.log(result.data);\n * }\n *\n * // Check storage quota\n * const quota = await storage.getQuotaInfo();\n * console.log(`Using ${quota.usagePercent}% of storage`);\n * ```\n */\nexport class SecureStorage implements SecureStorageInterface {\n  private readonly config: SecureStorageConfig;\n  private readonly encryptionKey: string;\n  private readonly storage: Storage;\n\n  constructor(\n    encryptionKey: string,\n    options: Partial<SecureStorageConfig> = {},\n    useSessionStorage = false\n  ) {\n    if (!encryptionKey || encryptionKey.length < 8) {\n      throw new Error('Encryption key must be at least 8 characters');\n    }\n\n    this.config = { ...secureStorageConfig, ...options };\n    this.encryptionKey = encryptionKey;\n\n    // Use sessionStorage or localStorage\n    this.storage = useSessionStorage ? window.sessionStorage : window.localStorage;\n  }\n\n  // ==========================================================================\n  // Core Operations\n  // ==========================================================================\n\n  /**\n   * Store an encrypted item\n   */\n  async setItem<T>(\n    key: string,\n    value: T,\n    options: SecureStorageSetOptions = {}\n  ): Promise<SecureStorageResult<void>> {\n    try {\n      const storageKey = this.getStorageKey(key);\n\n      // Serialize value\n      const serialized = JSON.stringify(value);\n\n      // Check size limit\n      if (serialized.length > this.config.maxItemSize) {\n        return {\n          success: false,\n          error: `Item exceeds maximum size of ${this.config.maxItemSize} bytes`,\n        };\n      }\n\n      // Determine compression setting\n      const shouldCompress = options.compress ?? this.config.compress;\n      const configForEncrypt = { ...this.config, compress: shouldCompress };\n\n      // Encrypt data\n      let encrypted = await encrypt(serialized, this.encryptionKey, configForEncrypt);\n\n      // Add expiration if TTL specified\n      if (options.ttl !== null && options.ttl !== undefined && options.ttl > 0) {\n        encrypted = { ...encrypted, expiresAt: Date.now() + options.ttl };\n      }\n\n      // Store encrypted data\n      const encryptedString = JSON.stringify(encrypted);\n\n      // Check if within quota\n      const currentSize = this.estimateStorageSize();\n      const newSize = currentSize + encryptedString.length * 2;\n\n      if (newSize > this.config.storageQuota) {\n        return {\n          success: false,\n          error: 'Storage quota exceeded',\n        };\n      }\n\n      this.storage.setItem(storageKey, encryptedString);\n\n      // Store metadata\n      const metadata = this.createMetadata(key, value, encryptedString.length, options);\n      this.storage.setItem(\n        `${this.config.storagePrefix}${METADATA_PREFIX}${key}`,\n        JSON.stringify(metadata)\n      );\n\n      return {\n        success: true,\n        metadata,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        error: error instanceof Error ? error.message : 'Unknown encryption error',\n      };\n    }\n  }\n\n  /**\n   * Retrieve and decrypt an item\n   */\n  async getItem<T>(key: string): Promise<SecureStorageResult<T>> {\n    try {\n      const storageKey = this.getStorageKey(key);\n      const encryptedString = this.storage.getItem(storageKey);\n\n      if (encryptedString === null || encryptedString === undefined || encryptedString === '') {\n        return {\n          success: false,\n          error: 'Item not found',\n        };\n      }\n\n      const encrypted = JSON.parse(encryptedString) as EncryptedData;\n\n      // Check expiration\n      if (\n        encrypted.expiresAt !== null &&\n        encrypted.expiresAt !== undefined &&\n        encrypted.expiresAt > 0 &&\n        Date.now() > encrypted.expiresAt\n      ) {\n        // Remove expired item\n        await this.removeItem(key);\n        return {\n          success: false,\n          error: 'Item has expired',\n        };\n      }\n\n      // Decrypt data\n      const decrypted = await decrypt(encrypted, this.encryptionKey, this.config);\n\n      // Parse value\n      const value = JSON.parse(decrypted) as T;\n\n      // Update last accessed time in metadata\n      this.updateLastAccessed(key);\n\n      return {\n        success: true,\n        data: value,\n        metadata: (await this.getMetadata(key)) ?? undefined,\n      };\n    } catch (error) {\n      return {\n        success: false,\n        error: error instanceof Error ? error.message : 'Unknown decryption error',\n      };\n    }\n  }\n\n  /**\n   * Remove an item\n   */\n  async removeItem(key: string): Promise<SecureStorageResult<void>> {\n    try {\n      const storageKey = this.getStorageKey(key);\n      this.storage.removeItem(storageKey);\n\n      // Remove metadata\n      this.storage.removeItem(`${this.config.storagePrefix}${METADATA_PREFIX}${key}`);\n\n      await Promise.resolve(); // Satisfy require-await lint rule\n      return { success: true };\n    } catch (error) {\n      return {\n        success: false,\n        error: error instanceof Error ? error.message : 'Failed to remove item',\n      };\n    }\n  }\n\n  /**\n   * Check if an item exists\n   */\n  async hasItem(key: string): Promise<boolean> {\n    await Promise.resolve(); // Satisfy require-await lint rule\n    const storageKey = this.getStorageKey(key);\n    const item = this.storage.getItem(storageKey);\n\n    if (item === null || item === undefined || item === '') {\n      return false;\n    }\n\n    // Check expiration\n    try {\n      const encrypted = JSON.parse(item) as EncryptedData;\n      if (\n        encrypted.expiresAt !== null &&\n        encrypted.expiresAt !== undefined &&\n        encrypted.expiresAt > 0 &&\n        Date.now() > encrypted.expiresAt\n      ) {\n        this.removeItem(key);\n        return false;\n      }\n      return true;\n    } catch {\n      return false;\n    }\n  }\n\n  /**\n   * Get all keys\n   */\n  async keys(): Promise<string[]> {\n    await Promise.resolve(); // Satisfy require-await lint rule\n    const prefix = this.config.storagePrefix;\n    const metaPrefix = `${prefix}${METADATA_PREFIX}`;\n    const keys: string[] = [];\n\n    for (let i = 0; i < this.storage.length; i++) {\n      const key = this.storage.key(i);\n      if (key?.startsWith(prefix) === true && !key.startsWith(metaPrefix)) {\n        keys.push(key.slice(prefix.length));\n      }\n    }\n\n    return keys;\n  }\n\n  /**\n   * Get storage quota information\n   */\n  async getQuotaInfo(): Promise<StorageQuotaInfo> {\n    const used = this.estimateStorageSize();\n    const total = this.config.storageQuota;\n    const available = Math.max(0, total - used);\n    const usagePercent = (used / total) * 100;\n    const keys = await this.keys();\n\n    return {\n      total,\n      used,\n      available,\n      usagePercent,\n      isNearLimit: usagePercent > 80,\n      itemCount: keys.length,\n    };\n  }\n\n  /**\n   * Clear all secure storage items\n   */\n  async clear(): Promise<SecureStorageResult<void>> {\n    await Promise.resolve(); // Satisfy require-await lint rule\n    try {\n      const prefix = this.config.storagePrefix;\n      const keysToRemove: string[] = [];\n\n      for (let i = 0; i < this.storage.length; i++) {\n        const key = this.storage.key(i);\n        if (key?.startsWith(prefix) === true) {\n          keysToRemove.push(key);\n        }\n      }\n\n      for (const key of keysToRemove) {\n        this.storage.removeItem(key);\n      }\n\n      // Clear key cache\n      keyCache.clear();\n\n      return { success: true };\n    } catch (error) {\n      return {\n        success: false,\n        error: error instanceof Error ? error.message : 'Failed to clear storage',\n      };\n    }\n  }\n\n  /**\n   * Get item metadata\n   */\n  async getMetadata(key: string): Promise<SecureStorageMetadata | null> {\n    await Promise.resolve(); // Satisfy require-await lint rule\n    try {\n      const metaKey = `${this.config.storagePrefix}${METADATA_PREFIX}${key}`;\n      const metaString = this.storage.getItem(metaKey);\n\n      if (metaString === null || metaString === undefined || metaString === '') {\n        return null;\n      }\n\n      return JSON.parse(metaString) as SecureStorageMetadata;\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Cleanup expired items\n   */\n  async cleanup(): Promise<number> {\n    let cleaned = 0;\n    const keys = await this.keys();\n\n    for (const key of keys) {\n      const storageKey = this.getStorageKey(key);\n      const item = this.storage.getItem(storageKey);\n      if (item !== null && item !== undefined && item !== '') {\n        try {\n          const encrypted = JSON.parse(item) as EncryptedData;\n          if (\n            encrypted.expiresAt !== null &&\n            encrypted.expiresAt !== undefined &&\n            encrypted.expiresAt > 0 &&\n            Date.now() > encrypted.expiresAt\n          ) {\n            await this.removeItem(key);\n            cleaned++;\n          }\n        } catch {\n          // Corrupted item, remove it\n          await this.removeItem(key);\n          cleaned++;\n        }\n      }\n    }\n\n    // Clear expired key cache\n    clearExpiredKeys(this.config.keyTtl);\n\n    return cleaned;\n  }\n\n  // ==========================================================================\n  // Helper Methods\n  // ==========================================================================\n\n  /**\n   * Get configuration\n   */\n  getConfig(): Readonly<SecureStorageConfig> {\n    return { ...this.config };\n  }\n\n  /**\n   * Get the full storage key with prefix\n   */\n  private getStorageKey(key: string): string {\n    return `${this.config.storagePrefix}${key}`;\n  }\n\n  /**\n   * Estimate total storage size in bytes\n   */\n  private estimateStorageSize(): number {\n    let totalSize = 0;\n    const prefix = this.config.storagePrefix;\n\n    for (let i = 0; i < this.storage.length; i++) {\n      const key = this.storage.key(i);\n      if (key?.startsWith(prefix) === true) {\n        const value = this.storage.getItem(key);\n        if (value !== null && value !== undefined) {\n          // UTF-16 encoding: 2 bytes per character\n          totalSize += (key.length + value.length) * 2;\n        }\n      }\n    }\n\n    return totalSize;\n  }\n\n  /**\n   * Create metadata for an item\n   */\n  private createMetadata<T>(\n    key: string,\n    value: T,\n    size: number,\n    options: SecureStorageSetOptions\n  ): SecureStorageMetadata {\n    const now = Date.now();\n\n    return {\n      key,\n      size,\n      createdAt: now,\n      lastAccessedAt: now,\n      expiresAt:\n        options.ttl !== null && options.ttl !== undefined && options.ttl > 0\n          ? now + options.ttl\n          : undefined,\n      type: this.getValueType(value),\n    };\n  }\n\n  /**\n   * Update last accessed time in metadata\n   */\n  private updateLastAccessed(key: string): void {\n    const metaKey = `${this.config.storagePrefix}${METADATA_PREFIX}${key}`;\n    const metaString = this.storage.getItem(metaKey);\n\n    if (metaString !== null && metaString !== undefined && metaString !== '') {\n      try {\n        const metadata = JSON.parse(metaString) as SecureStorageMetadata;\n        const updatedMetadata: SecureStorageMetadata = { ...metadata, lastAccessedAt: Date.now() };\n        this.storage.setItem(metaKey, JSON.stringify(updatedMetadata));\n      } catch {\n        // Ignore metadata update errors\n      }\n    }\n  }\n\n  /**\n   * Get the type of value for metadata\n   */\n  private getValueType(value: unknown): SecureStorageMetadata['type'] {\n    if (value === null) return 'object';\n    if (Array.isArray(value)) return 'array';\n    const type = typeof value;\n    if (type === 'string' || type === 'number' || type === 'boolean' || type === 'object') {\n      return type;\n    }\n    return 'object';\n  }\n}\n\n// ============================================================================\n// Factory Functions\n// ============================================================================\n\n/**\n * Create a secure localStorage instance\n */\nexport function createSecureLocalStorage(\n  encryptionKey: string,\n  options?: Partial<SecureStorageConfig>\n): SecureStorage {\n  return new SecureStorage(encryptionKey, options, false);\n}\n\n/**\n * Create a secure sessionStorage instance\n */\nexport function createSecureSessionStorage(\n  encryptionKey: string,\n  options?: Partial<SecureStorageConfig>\n): SecureStorage {\n  return new SecureStorage(encryptionKey, options, true);\n}\n\n// ============================================================================\n// Singleton Instance\n// ============================================================================\n\nlet defaultStorage: SecureStorage | null = null;\n\n/**\n * Initialize the default secure storage instance\n * Call this once during app initialization\n */\nexport function initSecureStorage(encryptionKey: string): SecureStorage {\n  defaultStorage ??= createSecureLocalStorage(encryptionKey);\n  return defaultStorage;\n}\n\n/**\n * Get the default secure storage instance\n * @throws Error if not initialized\n */\nexport function getSecureStorage(): SecureStorage {\n  if (!defaultStorage) {\n    throw new Error('Secure storage not initialized. Call initSecureStorage() first.');\n  }\n  return defaultStorage;\n}\n\n/**\n * Check if secure storage is available\n */\nexport function isSecureStorageAvailable(): boolean {\n  try {\n    if (typeof window === 'undefined') {\n      return false;\n    }\n\n    // Check for Web Crypto API\n    if (typeof crypto === 'undefined' || crypto?.subtle == null) {\n      return false;\n    }\n\n    // Check for localStorage\n    const testKey = '__secure_storage_test__';\n    window.localStorage.setItem(testKey, 'test');\n    window.localStorage.removeItem(testKey);\n\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Securely wipe a string from memory\n * Note: This is best-effort in JavaScript due to string immutability\n */\nexport function secureWipe(value: string): void {\n  // Create garbage to overwrite memory\n  const garbage = crypto.getRandomValues(new Uint8Array(value.length));\n  // This doesn't actually overwrite the original string in JS\n  // but it's a hint to the GC\n  void garbage;\n}\n\n/**\n * Generate a secure encryption key\n * Returns a base64-encoded key suitable for SecureStorage\n */\nexport function generateEncryptionKey(length = 32): string {\n  const bytes = getRandomBytes(length);\n  return bytesToBase64(bytes);\n}\n\n/**\n * Hash sensitive data for storage keys\n * Use when the key itself should not reveal information\n */\nexport async function hashForKey(data: string): Promise<string> {\n  const hash = await sha256(data);\n  // Return URL-safe version\n  return hash.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n// ============================================================================\n// Type Exports\n// ============================================================================\n\nexport type {\n  SecureStorageConfig,\n  SecureStorageInterface,\n  SecureStorageResult,\n  SecureStorageSetOptions,\n  SecureStorageMetadata,\n  StorageQuotaInfo,\n  EncryptedData,\n  EncryptionAlgorithm,\n  EncryptedString,\n};\n"],"names":["ENCRYPTION_VERSION","METADATA_PREFIX","keyCache","getRandomBytes","length","bytes","bytesToBase64","binString","byte","base64ToBytes","base64","char","sha256","data","hashBuffer","deriveKey","password","salt","config","encoder","keyMaterial","algorithm","derivedKeyAlgorithm","getCachedKey","cacheKey","cached","key","clearExpiredKeys","ttl","now","compress","stream","writer","reader","chunks","result","totalLength","sum","chunk","compressed","offset","decompress","decompressed","encrypt","iv","dataBytes","encrypted","encryptedBytes","ciphertext","tag","checksum","decrypt","encryptedData","decrypted","decryptedBytes","SecureStorage","encryptionKey","options","useSessionStorage","secureStorageConfig","value","storageKey","serialized","shouldCompress","configForEncrypt","encryptedString","metadata","error","item","prefix","metaPrefix","keys","i","used","total","available","usagePercent","keysToRemove","metaKey","metaString","cleaned","totalSize","size","updatedMetadata","type","createSecureLocalStorage","createSecureSessionStorage","defaultStorage","initSecureStorage","getSecureStorage","isSecureStorageAvailable","testKey","secureWipe","generateEncryptionKey","hashForKey"],"mappings":"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"}