题目与场景
应用在浏览器中加密本地数据,并希望跨会话使用密钥。设计应降低密钥暴露,但必须说明限制:同源脚本仍可能调用允许的操作,用户也可能失去恢复能力。
面试官在考察什么
- 理解安全上下文、CryptoKey 可导出性和密钥用途。
- 分离加密数据存储、密钥恢复与威胁建模。
- 解释浏览器密码学不能让 XSS 无害。
作答前的澄清问题
- 威胁是被盗存储记录、被动攻击者,还是主动同源脚本?
- 注销、设备丢失、密码重置和浏览器配置删除后数据是否必须保留?
- 能否用用户口令或 WebAuthn 凭据解锁包裹密钥?
- 需要哪些算法、用途、浏览器支持和迁移路径?
30 秒回答框架
我会要求 HTTPS,生成或导入 CryptoKey,把 extractable 设为 false,只授予必要用途,并把浏览器管理的密钥句柄存入 IndexedDB,而不是导出原始字节。密文、随机数、算法参数和版本与密钥分开保存。同时配置 CSP、依赖审查和恢复方案,并说明应用打开时同源脚本仍可能调用解密 API 或读取内存中的明文。
分步深挖
1. 定义威胁模型
不可导出性限制意外导出和部分存储盗窃路径,但不能阻止在同源执行的脚本请求应用解密或读取内存明文。承诺安全性前先声明边界。
2. 创建或导入密钥
使用受支持算法和专用用途,例如加密与解密。在安全上下文生成密钥,或导入包裹材料并设置目标可导出性。拒绝异常算法参数,不把原始密钥材料放进 localStorage。
3. 安全持久化密文
保存密文、每次加密的新随机数、认证元数据、密钥版本和数据模式版本。使用 AES-GCM 等认证加密,并保证同一密钥下每条记录的随机数唯一。把租户或用户范围放进关联数据,而不是隐含信任决策。
4. 规划恢复与轮换
浏览器配置删除或设备丢失可能让不可导出密钥无法使用。上线前提供明确恢复路径,例如口令派生的包裹密钥或服务端重新加密流程,不能静默降级为明文。密钥版本化并事务性迁移记录。
5. 测试与运营
测试不支持算法、不安全上下文、配额错误、中断写入、随机数复用、版本迁移、注销和恢复失败。配置 CSP、审查依赖、不记录敏感日志,只统计解密失败而不记录明文。
高质量示范回答
“我会要求 HTTPS,生成用途受限且 extractable 为 false 的 CryptoKey,只把浏览器管理的句柄放进 IndexedDB。每条记录保存密文、唯一随机数、认证元数据和密钥版本。由于配置丢失可能导致不可导出密钥无法恢复,我会在上线前定义恢复流程。CSP 与依赖控制能降低主动脚本风险,但同源 XSS 仍可能调用允许的解密操作或读取应用打开时的明文。”
常见失误
- 把原始密钥放入 localStorage → 存储被盗就能解密 → 持久化不可导出密钥句柄。
- AES-GCM 复用随机数 → 机密性与完整性可能失效 → 每个密钥和记录使用唯一随机数。
- 声称解决了 XSS → 同源代码仍能使用应用权限 → 说明主动脚本限制。
- 跳过恢复设计 → 配置丢失会毁掉数据访问 → 定义包裹、重置和迁移流程。
追问与回答
IndexedDB 能让密钥免受 XSS 吗?
不能。它避免把原始字节放进简单存储 API,但同源脚本仍可能访问数据库或调用应用代码。应配置 CSP、审查依赖并采用现实威胁模型。
用户丢设备后如何恢复?
用用户持有的秘密或恢复凭据派生密钥包裹数据密钥,或通过认证服务端流程重新加密。解释离线与重置取舍,不能静默生成无法解密旧数据的新密钥。
轮换时可以导出密钥吗?
只有策略允许才可以。更推荐生成新密钥,在两个版本都可用时迁移记录;需要包裹时保护包裹密钥并审计转换。