Unlock 页面删除与 PIN / 加密密钥界面边界

December 14, 2025
2 min read
By devshan

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

背景

  • 早期版本里存在一个 UnlockPage,用于输入“解锁密码/密钥”。
  • 后续引入了两套独立概念:
    • 应用层 PIN:只保护 UI 进入,需要本地验证,不参与加解密。
    • 端到端加密密钥(保险库密码):真正用于派生主密钥,加解密 S3 里的内容。
  • 再加上 HomePage 内联的解锁 UI,一度出现三个“解锁界面”的影子,极易混淆:
    • 当时不知道“这里是输入 PIN 还是输入加密密钥”。
    • 代码层面也有多处解锁逻辑入口,难以维护。

本次整理的目标是:给 PIN 和加密密钥明确边界,只保留必要的解锁界面

现状梳理

1. 应用 PIN 解锁流

  • 启动时是否需要 PIN,由本地偏好计算:
    • 入口:client/lib/main.dart:12-24
    • appPinRequired 综合了:
      • 是否设置过 PIN。
      • 是否勾选“启动时需要 PIN 解锁”。
      • 是否在 24 小时免输入窗口内。
  • 真正的 PIN 解锁界面:
    • 组件:AppPinLockPageclient/lib/ui/unlock_page.dart:7-54,56-135
    • 特点:
      • 只输入数字 PIN,不涉及密码派生。
      • 勾选“24 小时内不需要输入 PIN”后,会写入 app_pin_skip_until
      • 验证逻辑调用 AppState.verifyAppPinclient/lib/core/state/app_state.dart:286-289
      • 验证成功后直接导航到 HomePage
  • 这个界面只负责“保护 UI”,不触碰任何加密逻辑。

2. 端到端加密密钥解锁流

  • 解锁保险库的核心调用:
    • AppState.unlockclient/lib/core/state/app_state.dart:393-414
    • 再经由 ApiClient.unlockVault 调用后端 /api/v1/auth/unlock
      • client/lib/core/api/api_client.dart:137-153
  • UI 层不再单独弹出“密钥输入页”,而是使用 HomePage 的内联解锁区域:
    • 入口方法:_handleVaultUnlockclient/lib/ui/home_page.dart:142-164
    • 内联解锁组件:_buildVaultUnlockInlineclient/lib/ui/home_page.dart:707-745
    • 行为:
      • 我在主界面中直接输入“保险库密码”(端到端密钥)。
      • 成功后:
        • 前端保存密码(如果选择记住)。
        • 状态 _vaultStatus 变为已解锁,展示文件列表。
  • 这个流程与应用 PIN 完全解耦,只关心加密和 S3 数据。

3. 已废弃的 UnlockPage 问题

  • 旧的 UnlockPage 实际上已经不在导航链路里被使用,但代码还留在历史版本里。
  • 问题:
    • 名称与职责都模糊:“解锁”到底是 PIN 还是加密密钥?
    • 很容易和 AppPinLockPageHomePage 内联解锁搞混。
    • 对未来阅读者来说,这是一个没有上下文的“幽灵页面”。

决策与调整

决策:只保留两条明确的解锁路径

  • 路径 A:应用 PIN
    • 配置入口:设置页的“应用 PIN 码”和“启动时需要 PIN 解锁”:
      • client/lib/ui/settings_page.dart:115-167,445-473
    • 解锁界面:AppPinLockPage
    • 语义:保护 UI,不涉及加密。
  • 路径 B:端到端加密密钥(保险库密码)
    • 解锁界面:HomePage 内联的 _buildVaultUnlockInline
    • 语义:真正控制是否能读写 S3 中的加密内容。
  • 任何其他“解锁页面”都视为噪音,不再保留

实际改动要点

  • 保留 AppPinLockPage,确认其仅用于 PIN 流程:
    • 调用 verifyAppPin,根据结果决定是否进入 HomePage
    • 不触碰 unlockVault、不设置 master key。
  • 删除旧的 UnlockPage 实现及其引用:
    • 移除与端到端密钥相关但已不再使用的 UI 代码。
    • 确保路由和设置页中不再出现指向 UnlockPage 的导航。
  • 确认加密密钥输入只发生在 HomePage
    • 内联解锁负责密码输入和错误提示。
    • 成功后加载元数据列表。

收获

  • 从“有多个解锁页”收敛为:
    • PIN 解锁:纯本地 UI 保护。
    • 密钥解锁:在 Home 主界面内联完成。
  • 对我来说:
    • 不再出现“到底应该在这里输入 PIN 还是输入密码”的迷惑对话框。
    • 打开应用的第一屏逻辑更清晰:
      • 如果开启 PIN 保护:先输入 PIN。
      • 进入 Home 后,再根据 S3 状态决定是否需要输入保险库密码。
  • 对代码维护来说:
    • 只有一个 PIN 页面和一个密钥解锁区域,职责边界清晰。
    • 避免未来重构时又误用过时的 UnlockPage