Skip to content

双密码与伪装空间设计

1. 产品边界

主密码和假密码是本地 App Lock 凭据,不参与服务端认证。主密码进入真实 Profile;假密码从同一入口进入独立空白 Decoy Profile。假密码触发本地格式化是可选能力,默认关闭。

本设计降低旁观或胁迫解锁时直接暴露真实内容的风险,但不承诺对设备取证、操作系统失陷、长期行为观察或外部备份检查提供完全可否认性。

2. 来源分类

v1.1 MUST

  • 主/假密码互不相同,只在本地使用,不进入网络、日志、崩溃、分析或诊断。
  • 两个密码使用独立盐和内存困难 KDF;KDF 输出仅用于验证/解封随机密钥。
  • 同一输入界面路由 real / decoy / invalid;错误提示中性。
  • Decoy 使用独立容器,默认无真实身份、联系人、会话、服务器和备份痕迹。
  • 格式化默认关闭;启用需主密码、不可逆警告和二次确认。
  • 只有精确假密码验证成功可触发格式化;普通错误、Face ID 失败、取消、退后台或系统终止不得触发。

说明书建议

  • 默认至少 8 字符;纯数字 PIN 至少 6 位;具体口令策略和 KDF 参数需可用性、设备性能和审计共同决定。
  • 使用中性槽位名减少静态检查直接暴露语义,但这不构成取证不可区分证明。

当前已验证事实

  • 当前仓库没有 AppUnlock、Decoy Profile、通知或格式化实现;本文定义的是待实现/验证的状态机。

3. 安全目标与非目标

目标:

  • 未解锁前,UI 和业务层无法知道用户将进入 Real 还是 Decoy。
  • Decoy 运行期间不挂载、不查询、不通知、不导出 Real 数据。
  • 两种有效密码的验证路径尽量相近,不通过错误文案或明显时序暴露槽位。
  • 格式化关闭时,无论进入 Decoy 多少次,Real 密钥和数据均不变化。

非目标:

  • 隐藏 App 已安装、网络访问或外部加密备份的存在。
  • 抵抗已完全控制 iOS、键盘、屏幕录制或进程内存的攻击者。
  • 保证两条路径在所有硬件和系统状态下严格恒定时间。
  • 伪造真实社交历史或承诺“可信否认”;MVP Decoy 是自然空白空间。

4. 解锁状态机

当前状态事件条件动作新状态
Locked密码提交主槽验证成功解封 Real 主密钥,初始化 Real 容器RealUnlocked
Locked密码提交假槽成功,格式化关闭仅初始化 Decoy 容器DecoyUnlocked
Locked密码提交假槽成功,格式化开启进入中性维护/销毁协调器;不初始化 Real;完成或继续清理后打开 DecoyDecoyUnlocked
Locked密码提交两槽均失败增加本地延迟,不访问任何 ProfileLocked
LockedFace ID 成功用户允许快捷解锁只可解锁 Real;不得自动触发 Decoy/格式化RealUnlocked
任意锁定流程取消/退后台/系统终止任意不调用格式化入口;清理输入Locked
RealUnlocked/DecoyUnlocked超时/主动锁定任意释放对应容器和内存会话Locked

不允许“连续输错 N 次清空”。SecureEraseCoordinator 只能接收不可伪造的本地枚举结果 decoyAuthenticatedAndEraseEnabled,不能接收用户输入字符串或布尔组合。

5. 凭据记录候选

每个槽位至少包含:随机盐、KDF 算法/版本/参数、口令验证材料或密钥封装、创建版本。持久化键名使用中性编号;记录长度和访问控制尽量一致。

待总控决策 01 验证与解封结构

选项 A 两个槽位各自持有认证封装:主槽封装 Real 主密钥,假槽封装 Decoy 主密钥/格式化授权材料。

  • 优点:成功路径自然得到对应能力,不需要保存独立可比较 verifier。
  • 风险:封装格式或密钥存在差异可能泄露槽位;假槽不能获得 Real 主密钥。

选项 B KDF verifier 后再访问独立 Keychain 项:先判定槽位,再读取对应密钥。

  • 优点:实现直观。
  • 风险:显式 verifier、Keychain 访问模式和分支更容易暴露;错误 oracle 面更大。

推荐:优先验证 A 的平台可行性;槽位记录固定长度、同版本、相近工作量,假槽绝不包含可解封 Real 的材料。最终需 iOS 安全评审。

KDF 要求

  • Argon2id 或经审计确认的等价内存困难 KDF;参数按最低支持设备校准并设格式版本。
  • 两槽独立盐;域分离包含 App、槽位用途和格式版本。
  • 同一次提交对两个候选槽执行等价工作,避免“找到第一个即返回”的明显时序差异;实际侧信道仍需真机统计。
  • 参数解析有内存/时间上限,防止损坏记录造成拒绝服务。
  • 输入使用可控字节缓冲并尽快释放;不得写入自动填充、键盘学习或分析事件。

6. Decoy 数据边界

Decoy 必须有独立:

  • 数据库文件、WAL/SHM、附件、草稿、缓存和临时目录;
  • Keychain service/account 或 access group 内命名空间;
  • 依赖容器、路由、搜索索引、分享数据和诊断记录;
  • 通知显示状态和 badge 状态。

进入 Decoy 时不得:

  • 打开 Real 数据库来判断是否有内容;
  • 初始化 Real CryptoSessionActor、WebSocket、Push 映射或服务器 Profile;
  • 从 Real 复制联系人、头像、最近服务器或备份提示;
  • 记录“假密码命中”“格式化触发”等可识别日志。

默认界面表现为自然的首次使用/尚未创建身份状态。是否允许用户在 Decoy 中创建持久假身份属于后续产品范围,MVP 不预设。

7. 通知 后台与系统集成

  • App 进入后台立即使用与 Profile 无关的遮蔽画面。
  • 进入 Decoy 后清除当前可见 VMax 通知和 badge;Notification Service Extension 不得读取 Real 数据库生成摘要。
  • Decoy 运行时收到唤醒,只能静默标记“有待处理工作”,不能展示真实联系人或摘要;返回 Locked/Real 后再拉取处理。
  • Spotlight、Siri、Widget、Live Activity、分享扩展、快捷方式和系统搜索若不能证明按 Profile 隔离,MVP 默认不集成或不索引敏感数据。
  • Face ID 只能是 Real 的可选快捷入口;锁屏必须提供直接输入密码的路径。

具体 iOS 生命周期和通知接口交给 iOS/Push 任务实现。

8. 可区分侧信道与产品披露

侧信道风险缓解剩余边界
解锁耗时主/假/错误路径可被统计区分等价 KDF 工作、统一动画和错误系统负载和后续初始化仍可能不同
磁盘容量/文件数Real 数据量暴露文件保护、命名中性、Decoy 独立设备取证仍可能看出差异
Keychain 项槽位语义暴露中性键名、相同结构和访问控制高权限取证不在保证范围
通知与网络Decoy 时仍有真实活动无内容唤醒、清摘要、不加载 Real时间相关性仍可能被观察
外部备份.vmaxbak 暴露真实身份存在加密、中性元数据和用户提示App 无法删除外部副本
错误/日志直接记录槽位或格式化字段白名单和中性错误系统级日志需真机审计

设置和帮助文案应说明这是“伪装空间与本地数据保护”,而非不可被取证识别的保证。

9. 测试矩阵

  • 主正确、假正确、错误、空输入、取消、Face ID 成功/失败、退后台、kill/relaunch。
  • 格式化开/关各自执行上述矩阵;关闭时假密码 100 次不能改变 Real。
  • 两个以上服务器 Profile,检查数据库、Keychain、通知、缓存、搜索和剪贴板交叉访问。
  • Decoy 冷启动、后台唤醒、系统通知、分享扩展和诊断导出均不得出现真实数据。
  • 真机统计主/假/错误验证时延分布;把可稳定分类的差异列为安全问题,不伪称恒定时间。
  • 持久化结构静态检查不应出现 real_passwordfake_password 等语义名,但不得把通过此检查当作可否认性证明。

10. 独立审计问题

  • KDF/封装结构是否让假槽获得任何 Real 解封能力?
  • 同一次输入评估两个槽是否引入 DoS、时序或缓存侧信道?
  • Decoy 是否通过 SwiftUI 环境、单例、共享数据库连接、通知扩展或系统索引意外挂载 Real?
  • 格式化授权是否可能由伪造状态、损坏记录或迁移错误触发?
  • 进入 Decoy 前清通知是否本身形成明显信号;产品如何准确披露剩余风险?

系统初步设计 · 待决事项不代表批准 · 安全方案尚未完成独立审计