indexeddb 本身不加密,敏感数据必须用 web crypto api 的 aes-gcm 前端加密后存储,密钥须由用户密码动态派生且绝不硬编码或持久化,配套 https、csp 等防御措施。

IndexedDB 本身不加密,所有敏感数据必须在写入前由前端代码加密,读取后解密。这不是可选优化,而是安全底线——否则数据以明文形式躺在用户硬盘上,任何能访问浏览器存储的程序(包括恶意扩展、本地木马)都可直接读取。
用 Web Crypto API 做端到端加密
别用 Crypto.js 或自研方案,直接使用浏览器原生 Web Crypto API,它支持经验证的 AES-GCM 算法,兼顾加密与完整性校验:
- 每次加密必须生成全新随机 IV(推荐 12 字节),和密文一起存入 IndexedDB;IV 复用或固定等于放弃安全性
- 密钥长度不低于 256 位,调用
encrypt({ name: 'AES-GCM', iv }, key, data)得到密文和认证标签 - 解密时必须校验 GCM 标签,失败即拒绝解析,不抛出含调试信息的错误
- 避免 AES-CBC、XOR、Base64 等无认证机制的“伪加密”,它们无法防篡改
密钥不能硬编码,也不能存进数据库
密钥是整个链条最脆弱的一环。它绝不能出现在源码里、不许以字符串形式长期驻留内存、更不可存进 IndexedDB 或 localStorage:
- 密钥应由用户输入(如登录密码)动态派生:用 PBKDF2 或 HKDF,配合服务端下发的 salt(防彩虹表)
- 派生出的
CryptoKey对象不可序列化,仅用于encrypt()/decrypt(),作用域结束自动释放 - 用户登出时主动清理内存中残留的密钥句柄,避免被快照或调试工具捕获
- 高敏场景可结合 WebAuthn,用生物认证触发密钥解锁,密钥本身不出设备安全区
加密不是万能的,需配套防御措施
加密只解决静态数据泄露问题,其他攻击面仍需覆盖:
- 数据库名、objectStore 名、索引名保持中性,不暴露业务含义(例如不用
user_payment_info) - 启用 HTTPS 和 Secure Context,防止密码输入过程被中间人劫持
- 设置严格 CSP 策略,限制内联脚本与未授权域名资源加载,降低 XSS 泄密风险
- 敏感操作(如密钥派生、解密)尽量放在独立 iframe 或弹窗中执行,隔离执行上下文
推荐轻量级封装方案:Web Crypto Storage
若不想从零实现,可用开源库 Web Crypto Storage,它已整合 Web Crypto API 与 IndexedDB:
- 自动处理密钥派生、IV 生成、GCM 认证、数据序列化等细节
- 密钥仅存在于内存,且衍生密钥不可逆,原始密码丢失即永久无法解密历史数据
- 依赖精简(仅 IDB + Web Crypto Tools),无运行时漏洞风险
- 提供 Promise 接口,适配现代前端工程流,如与 Dexie.js 或 IDB 的封装层协同使用











