外观
VMax MVP 密钥生命周期
1. 状态与原则
本文定义密钥从生成、使用、轮换、备份到失效的设计约束。它不冻结具体协议、数据库、备份 KDF 或 Secure Enclave API;这些分别依赖 ADR-001、ADR-002、ADR-005 和 ADR-007。
原则:
- 私钥和会话秘密只在客户端生成和使用;服务端只持有公开材料与撤销状态。
- 口令只用于派生验证/解封材料,不直接充当数据库密钥。
- 每个 Profile 和 Real/Decoy 空间使用独立命名空间与随机主密钥。
- 删除优先删除“解封能力”,但不得把 Keychain 删除或内存清零描述成物理擦除。
- 所有轮换、删除和恢复均版本化、可测试,并保留必要但最小的安全事件。
2. 来源分类
v1.1 MUST
- 身份/设备私钥本机安全生成,不明文上传或写日志。
- 本地数据库随机主密钥由 Keychain 中受保护材料解封;主/假密码不能直接作为数据库密钥。
- 主/假密码使用不同随机盐与内存困难 KDF。
- 格式化先删除真实 Profile 的数据库密钥、身份/设备私钥封装材料和会话关键材料,再清理文件。
- 身份密钥变化触发联系人警告和验证降级。
建议方案
- 签名预密钥 7 天或 1000 次轮换、PQ 材料 50 条/24 小时注入等参数来自说明书建议,仍须审计和测量。
- Keychain + Secure Enclave 封装是平台候选;可用算法、访问控制、备份/迁移语义待 iOS 实证。
当前已验证事实
- 当前仓库没有生产密钥实现,未验证 Keychain 访问组、Secure Enclave 封装、SQLCipher、备份恢复或内存清零行为。
3. 密钥层级候选
text
用户本地凭据
├─ 主密码 --KDF(独立盐/参数/域)--> 主槽验证与解封材料
└─ 假密码 --KDF(独立盐/参数/域)--> 假槽验证与 Decoy 路由材料
设备保护根(平台受保护私钥或等价机制)
└─ 封装随机 Profile Data Master Key(每个 Profile 独立)
├─ 数据库密钥封装/派生
├─ 身份与设备私钥封装
├─ 会话状态封装
└─ 附件/缓存子密钥(带域分离)最终方案不得让单一 KDF 输出在验证、数据库加密、备份和网络协议之间复用。域分离标签须包含用途、Profile 稳定标识和格式版本。
4. 生命周期清单
| 密钥/材料 | 生成 | 持久化 | 使用 | 轮换/失效 | 删除验证 |
|---|---|---|---|---|---|
| 实例长期签名私钥 | 实例受控环境 | 服务端秘密管理/HSM 候选 | 签名实例配置 | 运维事件;需签名过渡方案 | 旧公钥吊销与客户端阻断测试;本任务仅提约束 |
| 身份私钥 | 客户端安全随机源 | 由 Profile 主密钥封装 | 授权设备/预密钥、身份证明 | 仅新身份或恢复冲突 | 旧联系人立即降级;旧封装不可解封 |
| 设备认证私钥 | 客户端安全随机源 | 独立封装/Keychain | challenge 签名 | 主动轮换、恢复、安全事件 | 服务端拒绝撤销设备;本地旧材料不可用 |
| 签名预密钥私钥 | 客户端安全随机源 | 加密持久化 | 异步握手 | 周期/使用数,参数待审计 | 过渡窗口后拒绝旧 key id |
| 一次性预密钥私钥 | 客户端批量生成 | 加密持久化 | 单次异步握手 | 使用即消费 | 并发和重放下至多一次成功 |
| 会话根/链密钥 | 握手及 ratchet 派生 | 加密会话状态 | 派生后续密钥 | 每步推进 | 旧状态不能被回滚加载 |
| 消息密钥 | 链密钥单次派生 | 原则上不持久化;跳跃缓存例外 | 单条 AEAD | 使用/过期后删除 | 重放和恢复测试;内存清零仅尽力而为 |
| 附件密钥 | 每附件安全随机生成 | 仅经 E2EE 消息传递;上传端临时加密保存 | 分片 AEAD | 附件完成/删除 | 对象存储仅见密文;MVP 附件为 P1 |
| Profile Data Master Key | Profile 创建/恢复时随机生成 | 仅保存封装形式 | 解封数据库及子密钥 | 恢复、安全重置、格式化后重建 | 删除关键封装后旧库无法打开 |
| Decoy Data Master Key | Decoy 初始化时独立随机生成 | 独立命名空间 | 仅 Decoy 数据 | 重置 Decoy | 不影响 Real;反向亦然 |
| 备份内容密钥 | 每次备份随机生成 | 由备份密码 KDF 产生的 KEK 封装 | 加密备份包 | 每次备份新建 | 错误密码/篡改在恢复前失败 |
5. 生成要求
- 只使用操作系统认可的密码学随机源;测试固定随机源必须与生产构建物理/配置隔离。
- 生成失败必须失败关闭,不能回退到时间戳、UUID、进程随机或可预测种子。
- key id 是非秘密引用,不能由私钥明文或可逆材料直接派生。
- 每种密钥记录算法、版本、创建原因和状态,但日志不记录原始密钥、完整地址或口令槽命中。
6. 使用与内存边界
- 解封动作集中在密码会话/安全存储边界,UI 只接收验证后的领域结果。
- 不让秘密类型实现默认字符串化、序列化、镜像反射或可随意复制的调试描述。
- 尽量缩短 Swift 与 FFI 两侧的秘密缓冲生命周期;避免不可控的
String保存口令。 - 内存清零是尽力控制复制和驻留的防护,不可声称已清除编译器、系统交换、崩溃转储或操作系统持有的所有副本。
- 后台、锁屏、Profile 切换和 Decoy 路由时,关闭网络任务并销毁内存会话对象;持久化状态仍保持加密。
7. 轮换与并发
待总控决策 01 预密钥和 PQ 注入周期
选项:
- 使用说明书建议值(签名预密钥 7 天/1000 次;PQ 50 条/24 小时)。优点是有初始基线;缺点是没有负载、耗电和审计证据。
- 由协议规范固定单一参数。优点是互操作稳定;缺点是未来调整需版本迁移。
- 由签名策略下发有界参数。优点是可运维;缺点是扩大降级与配置攻击面。
推荐:安全下限写入协议版本,只允许实例签名策略在审计过的范围内更频繁轮换;最终值待审计和真机测量。
并发要求:
- 会话状态由单一串行所有者管理;数据库写入带旧版本条件或事务锁。
- 同一一次性预密钥的领取/消费具有唯一状态转移;重复响应不生成不同会话。
- 同一消息重试复用逻辑消息标识,但是否复用密文必须由最终协议明确,不能临时决定。
8. 备份与恢复
- 备份包必须版本化、认证加密并在解密任何秘密前验证外层结构、KDF 参数上限和完整性。
- 备份 KDF 与 App Lock KDF 使用独立盐、域和参数;参数防止攻击者提交导致内存耗尽的备份。
- 恢复不得静默覆盖本机身份;冲突必须创建明确的恢复事务,并触发旧设备风险提示。
- 恢复后重新生成本机数据库主密钥和封装;不得继续把备份内容密钥当作运行时数据库密钥。
- 是否恢复会话状态需由 ADR-007 决定;恢复旧 ratchet 状态可能导致密钥/序号回退,默认应谨慎关闭或强制新会话。
9. 格式化与删除
- 先建立已验证的格式化意图和可恢复状态标记,再停止 Real Profile 的全部访问。
- 删除 Profile Data Master Key 的所有有效封装、身份/设备私钥封装和会话关键材料。
- 重新尝试解封,必须失败;若删除接口失败,保持锁定并继续收敛,不加载 Real。
- 再删除数据库、WAL/SHM、附件、草稿、缓存、临时文件、诊断日志和本地通知。
- 外部
.vmaxbak、系统/用户已经复制的文件、服务器 TTL 内密文不在本地删除保证内。 - Keychain 删除和文件删除不证明 NAND 物理覆写;产品只能称“本地格式化/密码学擦除”。
详细状态机见 docs/security/本地格式化与密码学擦除.md。
10. 验证清单
- 对每类密钥记录生成源、命名空间、可访问条件、备份属性、迁移属性和删除 API 实测结果。
- 真机覆盖冷启动、设备锁定、Face ID 失败、系统终止、升级、恢复、磁盘满和 Keychain 故障。
- 数据库快照、WAL/SHM、崩溃包、日志、通知、剪贴板和诊断导出做残留扫描。
- 格式化每一步 kill/relaunch,结果只能是完整可用或不可解封;不得出现旧状态回退。
- 独立审计确认 KDF 校准、域分离、Secure Enclave 假设、密钥复制和删除语义。
11. 待决问题
- Secure Enclave 能否以目标 iOS 版本的公开 API 完成所需封装及访问控制,还是需要 Keychain 保存由设备保护密钥包装的材料?
- App Lock KDF 参数如何按设备校准并避免验证时序暴露主/假槽?
- 备份是否包含会话恢复材料;若包含,如何阻止 ratchet 回滚?
- 身份恢复与旧设备撤销如何在 MVP 单设备边界内表达?
- 上游协议实现是否自行管理密钥持久化,VMax 能否满足其线程、备份和删除约束?