外观
VMax MVP 威胁模型
1. 状态与结论边界
- 文档状态:设计基线,尚未完成独立安全审计。
- 范围:同一实例、单设备、一对一文本通信,以及身份创建、联系人验证、离线投递、加密备份、私有服务器 Profile、本地双密码入口和可选本地格式化。
- 不在本模型内:群聊、多设备同时在线、跨实例联邦、语音视频、公开目录、Web 管理后台。
- 本文不证明某一密码组合安全,不声明“绝对安全”“与 Signal 同级”,也不证明 iOS 闪存物理擦除。
2. 来源分类
2.1 v1.1 MUST
- 服务端、对象存储和 Push Gateway 不得接触消息明文、私钥或会话密钥。
- 身份和设备私钥必须在本机安全生成;服务端认证使用设备签名,不使用主密码或假密码。
- 未知协议版本必须拒绝;协议解析必须有长度、版本和未知字段策略。
- 每个服务器 Profile 的数据库、Keychain 命名空间、身份和通知路由隔离。
- 主密码与假密码只在本机使用;假密码进入独立空白空间。
- 可选格式化默认关闭,且只能在精确验证假密码后触发;普通错误、Face ID 失败、取消、退后台和系统终止不得触发。
- 日志、崩溃报告、分析和诊断导出不得包含消息正文、私钥、备份密码、完整地址、APNs token、主/假密码或可逆口令材料。
- 生产发布前完成独立密码学审计、渗透测试、隐私与合规检查。
2.2 说明书建议,尚非已验证事实
- “X25519 + ML-KEM/X-Wing + PQXDH 风格握手 + Double Ratchet/Sparse PQ Ratchet/Triple Ratchet”是候选组合,不是已审计实现。
- Secure Enclave 封装、本地数据库技术、Argon2id 参数和密钥轮换周期仍需平台验证、性能测量与审计。
- 透明日志为 P1 候选,不能作为 MVP 已存在的防护。
2.3 当前已验证事实
- 仓库当前只有设计骨架;没有可供本任务验证的生产密码实现、服务端或 iOS 运行路径。
- v1.1 原始 DOCX 明确列出上述产品边界、MUST、发布硬门槛和不保证项。
- 本任务只建立可测试的设计约束;所有运行时结论仍待实现和测试。
2.4 已确定的工程路线约束
- 客户端采用 iOS Swift + SwiftUI,秘密状态不得穿透到通用 UI 环境、默认调试描述或跨 Profile 单例。
- 后端采用 Go + Docker;容器边界不是密码边界,镜像、环境变量、挂载、健康检查和 core dump 仍需秘密审查。
- PostgreSQL 保存公开身份材料、状态和密文信封,不得保存消息明文或私钥。
- Redis/队列只用于短期速率限制、在线状态、任务去重或投递协调,不得成为消息唯一存储,也不得出现明文、私钥或长期关系图谱。
- S3 兼容对象存储只保存客户端加密对象;图片、视频和附件不进入一对一文本 MVP,启用前需单独完成分片 AEAD、元数据、配额和删除设计。
- 不设管理后台;运维接口/CLI 仍必须最小权限、强认证和可审计,且不能获得消息明文。
3. 资产与敏感度
| 资产 | 期望属性 | 主要失效影响 |
|---|---|---|
| 身份私钥、设备私钥 | 机密、完整、可撤销或轮换 | 身份冒用、联系人信任被破坏 |
| 签名预密钥、一次性预密钥私有部分 | 机密、绑定身份、正确消费 | 首次会话被冒用、重放或降级 |
| 会话根密钥、链密钥、消息密钥 | 机密、单调推进、旧状态删除 | 历史或未来消息泄露 |
| 本地数据库随机主密钥 | 机密、只经受控槽位解封 | 整个真实 Profile 泄露 |
| 主密码、假密码及 KDF 材料 | 机密、不可从遥测外泄 | 真实空间暴露、伪装关系暴露 |
| 联系人验证状态和密钥变化记录 | 完整、不可静默提升 | 中间人攻击被错误显示为已验证 |
| 密文信封和路由元数据 | 内容机密、最小留存、可重试 | 关系图谱、流量分析、消息丢失或重复 |
| 备份包和备份密码 | 机密、完整、版本化 | 长期身份及历史泄露、回滚攻击 |
| 实例长期签名公钥和固定记录 | 完整、可核验变化 | 被导向恶意实例或配置 |
4. 信任边界
- iOS 端点边界:明文、私钥和真实 Profile 数据只应出现在受控客户端进程、加密数据库或系统安全存储中。操作系统完全失陷不在保证范围内。
- Real 与 Decoy 边界:两者必须是不同容器和命名空间;Decoy 不得实例化真实数据库、真实会话 actor、真实 Push 路由或真实服务器对象。
- Profile 边界:实例 A 的身份、数据库、Keychain、连接和通知不得被实例 B 复用。
- 消息实例边界:服务端可认证设备、路由密文和观察元数据,但不被信任读取内容或替换已验证身份而不被发现。
- Push 边界:消息实例只能交付随机路由引用和无内容唤醒;Push Gateway 与 APNs 不得获得密文信封或可读联系人信息。
- 备份边界:导出的
.vmaxbak离开 App 沙箱后不再受本地格式化控制;只有备份加密和用户保管策略继续保护它。 - 后端存储边界:PostgreSQL 是密文及状态的权威持久层;Redis/队列故障、丢失或重放不能造成消息永久丢失、重复交付或预密钥重复消费。S3 在 MVP 未启用,未来对象只能是端点加密内容。
与 iOS、服务端和 Push 的具体接口由对应任务设计;本文件只规定它们必须维持的安全边界。
5. 攻击者与攻击路径
| 攻击者 | 能力 | 可复现攻击路径 | 影响 | 必需控制 |
|---|---|---|---|---|
| 被动网络观察者 | 记录 IP、时间、大小和 TLS 流量 | 长期收集流量并关联收发时间 | 元数据画像;未来解密尝试 | TLS、E2EE、最小元数据、填充类别;不承诺隐藏流量分析 |
| 恶意消息实例 | 替换预密钥、重放信封、保留密文 | 返回旧身份包或重复 message_id | 中间人、重复消息、状态分叉 | 身份签名、二维码/安全码验证、密钥变化阻断、重放状态、TTL |
| 恶意 Push Gateway | 记录路由和时间、伪造唤醒 | 关联 wake_route_id 与活动 | 活动图谱、耗电拒绝服务 | 随机可轮换路由、无内容 payload、限流、最小日志 |
| 恶意联系人 | 发送畸形、超长、乱序或高跳跃消息 | 构造边界长度或巨大 ratchet gap | 崩溃、内存/CPU 耗尽、状态失步 | 严格解析、大小/跳跃上限、模糊测试、事务性状态推进 |
| 丢失设备持有者 | 接触锁定设备和本地备份 | 离线猜测 App 密码或备份密码 | 本地历史和身份泄露 | 内存困难 KDF、系统数据保护、速率限制、独立备份 KDF |
| 胁迫者/旁观者 | 观察解锁和页面、要求输入密码 | 比较时序、通知、容量或系统痕迹 | 发现真实空间存在 | 中性入口、独立 Decoy、相近验证路径、通知/快照清理;不承诺可否认性 |
| 供应链攻击者 | 注入依赖或构建产物 | 修改密码实现、日志或随机源 | 全局密钥泄露 | 锁定依赖、SBOM、签名构建、许可和来源审查、可复现验证 |
| 短暂端点入侵者 | 读取当前会话状态 | 获取当前根/链密钥后失去访问 | 部分历史/未来消息泄露 | 前向保密、可信密钥更新后的入侵后恢复;边界须由协议审计确认 |
6. 安全不变量
以下不变量必须转化为跨语言向量、单元/集成测试或真机检查;仅有接口成功响应不算通过。
- 端点持钥:服务端、对象存储、Push Gateway 和 APNs 永远不能获得消息明文、私钥、附件密钥或会话密钥。
- 实例绑定:身份包、认证 challenge、协议握手和消息 AAD 必须绑定实例标识;从实例 A 复制到实例 B 必须验证失败。
- 身份绑定:设备密钥、签名预密钥和一次性预密钥必须能追溯到已验证身份;任一签名或版本不符必须失败关闭。
- 不降级:未知版本、套件或能力组合必须拒绝;不能在既有会话中静默切换较弱套件。
- 唯一使用:一次性预密钥只能原子消费一次;消息密钥和 AEAD nonce 在同一密钥下不得复用。
- 状态原子性:明文交付、ratchet 状态推进和去重记录必须形成一致事务;崩溃后不能重复交付或回退密钥状态。
- 有界解析:密文、跳跃密钥、附件元数据、嵌套层级和未确认请求都有明确上限。
- 验证不静默提升:密钥变化立即使 L1/L2 降级并阻断安全显示;只有用户重新验证才能恢复。
- Profile 隔离:任何查询、通知、搜索、分享扩展或诊断都不能跨 Profile 或跨 Real/Decoy 访问。
- 密码本地性:主/假密码及其验证结果不进入网络、日志、崩溃包、分析或导出诊断。
- 格式化精确触发:只有“已启用 + 精确假密码验证成功”可进入销毁流程;其他事件路径的销毁调用次数必须为零。
- 先失钥后清文件:格式化以删除解封真实数据所需的关键材料为第一安全目标;崩溃恢复只能落在“真实密钥仍完整可用”或“真实密钥已不可恢复”之一。
7. 关键失败情形与验证
| 失败情形 | 安全响应 | 验证方式 |
|---|---|---|
| 服务端返回未知协议版本或套件 | 拒绝建立/继续会话,不回退 | 篡改向量、降级集成测试 |
| 一次性预密钥并发领取 | 至多一个握手成功消费 | 并发事务测试和重复请求测试 |
| 消息乱序、重复、重放 | 有界缓存;每个逻辑消息最多交付一次 | 100 条乱序、重复和重放向量 |
| ratchet gap 超限 | 拒绝且不破坏旧会话状态 | 边界值和状态快照比较 |
| 日志或崩溃采集异常 | 敏感字段仍被结构化拒绝/脱敏 | 自动扫描、人工抽样、故障注入 |
| Decoy 启动收到真实 Push | 不展示摘要,不挂载真实数据 | UI 测试、通知扩展集成测试 |
| 格式化任一步骤被系统终止 | 下次启动继续安全收敛;不加载真实数据 | 每一步 kill/relaunch 真机测试 |
| Keychain 删除失败 | 保持锁定/中性空白状态并重试,不宣称完成 | 故障注入和残留扫描 |
| 外部备份仍存在 | 明确不在清理范围,不做成功误报 | Files/iCloud Drive 人工测试与文案检查 |
8. 待总控决策
- 协议实现与许可:见
docs/adr/ADR-001-协议实现与许可.md。 - 身份地址和实例短码:见
docs/adr/ADR-003-身份地址与实例短码.md。 - 确定性序列化:见
docs/adr/ADR-004-规范化序列化格式.md。 - 双密码与格式化状态机:见
docs/adr/ADR-011-双密码伪装与格式化.md。 - iOS 最低版本、数据库、备份 KDF、Push 隐私和日志细节分别依赖 ADR-002、005、006、007、008;本任务不替对应线路冻结实现。
9. 独立审计问题
- 协议组合是否保留公开规范证明所依赖的 transcript、身份绑定、密钥确认和删除假设?
- PQ 与经典材料组合是否存在“任一分支失败即整体降级”、算法混淆或未知版本解析问题?
- ratchet 状态、去重记录和数据库事务在崩溃/并发下是否可能回滚或复用密钥?
- Swift/FFI 边界是否复制、日志化或延长秘密内存生命周期?所谓内存清零是否只有尽力而为的效果?
- Keychain/Secure Enclave 的访问控制、备份迁移和删除语义是否符合真实威胁模型?
- Real/Decoy 是否能通过时序、容量、通知、备份、系统搜索、分享扩展或错误状态区分?产品应明确哪些侧信道不保证隐藏。
- 格式化中断恢复是否可能误删、漏删或留下可解封密钥?外部备份边界是否准确展示给用户?