从 0 设计一个纯本地密码管理器:分层架构、AES-256-GCM 加密与多端扩展思路

36 阅读3分钟

最近用 AI Agent 辅助完成了一个纯本地密码管理器(代号"灵钥 LingKey")的完整方案设计,从需求规格到架构设计再到多端扩展,沉淀了一些架构层面的思考,记录下来供参考。

一、为什么做纯本地密码管理器 现有密码管理器多为云端订阅制,用户对"数据上云"存在顾虑。核心设计目标就三条:集中记录、快速检索、全程本地 AES-256 加密不上传。

二、分层架构设计 采用经典分层架构 + 服务化,UI 与业务逻辑解耦: 表现层(PyQt6):登录页 / 主列表 / 编辑弹窗 / 设置页 应用服务层:VaultService / RecordService / TagService / BackupService / LockManager 领域安全层:CryptoService / PasswordToolkit / 实体模型 数据访问层:RecordRepository / TagRepository 存储层:SQLite(vault.db)/ config.json / 加密备份文件 这样分层的收益是:核心加密逻辑与 UI 完全解耦,便于单元测试,也便于后续替换前端(比如换成 Flutter 做移动端)。

三、加密方案(核心) 密钥派生用 Argon2id,加密用 AES-256-GCM:

from argon2.low_level import hash_secret_raw, Type
key = hash_secret_raw(
    secret=master_password.encode(),
    salt=salt,
    time_cost=3,
    memory_cost=65536,   # 64MB
    parallelism=4,
    hash_len=32,
    type=Type.ID
)
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
aesgcm = AESGCM(key)
nonce = os.urandom(12)
ciphertext = aesgcm.encrypt(nonce, plaintext, None)

四、三个关键设计点:

  1. 密码字段密文入库,明文零落盘;
  2. 解锁时派生密钥,锁定时立即清零内存;
  3. 数据库写入用事务,避免异常退出的半写状态。 四、数据模型 核心是 records / tags / record_tags / vault_meta 四张表,敏感字段(url、username、notes)加密存储,password 单独存密文 + IV:
CREATE TABLE records (
  id           TEXT PRIMARY KEY,
  title        TEXT NOT NULL,
  type         TEXT NOT NULL,
  url_or_path  TEXT,
  username     TEXT,
  password_enc BLOB NOT NULL,
  password_iv  BLOB NOT NULL,
  notes_enc    BLOB,
  created_at   TEXT NOT NULL,
  updated_at   TEXT NOT NULL,
  deleted_at   TEXT
);

五、多端扩展:一核一密多壳 这是设计中最有意思的部分。跨多端做密码管理器,最容易犯的错是"每端各写一套",导致加密格式不一致。我的思路是:

  • 一核:定义与语言无关的《加密容器格式规范》,所有端严格按同一规范实现;
  • 一密:用户只有一个主密码,多端同步的永远是密文,密钥不出设备(端到端加密);
  • 多壳:UI 和系统集成用各端原生壳实现。 各端选型:iOS/Android 用 Flutter(~90% 复用),鸿蒙必须用 ArkTS 原生(不兼容 APK),浏览器插件用 WebExtension。 一个关键认知转变:移动端"搜集"模式从 PC 的"我去读别人"反转为"别人来问我"(系统级 AutoFill),这也是 1Password/Bitwarden 在手机上的工作方式。 六、小结 纯本地密码管理器的架构核心是"加密分层 + 密钥生命周期管理 + 多端格式统一"。本次方案设计过程中,我用 AiPy 辅助完成了文档产出与架构梳理,但加密方案与数据模型的关键决策仍然自己把关。