// DOCS · 账号保险库

账号保险库 · Account Vaultv2 · 2026-08-07

统一记录 AI 平台的 API Key / token / 密码,密文存储、浏览器本地解密。本文说明架构、解密设计、v2 修复内容与当前状态。

⚡ 三步速查 · 忘了怎么用就看这里
  1. 打开 likun.im/accounts/ 任何设备、任何浏览器都能开,页面本身不含任何明文。
  2. 输入解锁口令(VAULT_MASTER,64 位十六进制) 口令不写在本文档里(本页是公开 URL)。直接问八戒要就行——说一句「给我保险库的口令」,它会即时读出来给你,不需要你自己记、也不需要另存到别处。 若手边有终端也可自取: bash ~/.workbuddy/skills/account-vault/scripts/master-guard.sh --show
  3. 搜索并取值 解锁后在搜索框输关键词(如 deepseek)过滤,点「显示」看明文、点「复制」拷走。默认脱敏显示前 6 后 4 位。
🛡️ 口令已做三点冗余(2026-08-07 起)。 你不需要自己记、也不需要另存到钥匙串或备忘录——VAULT_MASTER 现在同时保存在三个物理位置,每天 08:00 自动体检,任一处丢失会用其余副本自动补回。需要时问八戒即可。详见第 8 节。
⚠️ 但底线仍在:三处全丢 = 数据永久报废。 本库无找回机制、无后门。2026-08-05 那批条目就是在冗余机制建立之前、因口令丢失而永久不可解的(见第 4 节)。冗余大幅降低了概率,但不改变"丢了就没了"这个性质。
v2 更新(2026-08-07): 修复三处致命 bug(线上页面此前输入任何密码都解不开)、新增关键词搜索、引入历史条目(legacy)机制。线上库与本地库已合并为单一数据源。

1. 它是什么

一处存、两处取的密钥保险库。敏感值一律 AES-256-GCM 加密,服务器与仓库里只有密文。

入口形态怎么解锁
/accounts/网页端,纯前端解密浏览器输入 VAULT_MASTER
WorkBuddy 对话account-vault 技能(CLI)自动读 .env 的 VAULT_MASTER

数据真相源是本地 ~/.workbuddy/accounts/vault.json;网页端的 accounts/vault.json 是它的只读副本,由同步脚本推送。

2. 解密设计

网页端与 CLI 参数完全一致,否则互相解不开:

PBKDF2(master, salt, 100000 次, SHA-256)
  → AES-256-GCM(iv 12 字节,authTag 独立存储)

master = VAULT_MASTER,一串 64 位十六进制(不是人类口令)
每条 entry 都有自己独立的随机 salt —— 必须逐条派生 key
解密全程在浏览器本地用 Web Crypto 完成,主密码与明文不离开本机

数据结构

{
  "entries": [
    {
      "name": "DeepSeek Codex",
      "secret": { "salt": "…", "iv": "…", "tag": "…", "data": "…" },
      "description": "DeepSeek API key,Codex 用",
      "created": "2026-08-07T03:02:09.170Z",
      "legacy": false          // true = 旧 master 加密,已不可解
    }
  ]
}

使用步骤(网页端)

  1. 打开 /accounts/
  2. 粘贴 VAULT_MASTER(64 位 hex),点「解锁」
  3. 用搜索框输关键词(如 deepseek、智谱)实时筛选,Esc 清空
  4. 密钥默认脱敏(前 6 + 后 4),点「显示」出明文,「复制」写剪贴板

3. v2 修复了什么

旧版网页端存在三个叠加的 bug,导致无论输入什么主密码都提示「密码错误」——保险库实际上一直打不开:

#Bug后果
1读 entry.salt,而真实结构是 entry.secret.salt字段全 undefined,必然抛错
2只用第一条的 salt 派生一个 key 去解全部条目每条 salt 都不同,第 2 条起必失败
3主密码校验只试第一条第一条若不可解,整库误判「密码错误」

v2 的处理:兼容两种数据结构、逐条独立派生 key、校验规则改为「任一条能解开即通过」。

4. 历史条目(legacy)机制

⚠️ 2026-08-07 事故: 技能 .env 一度缺失,助手直接生成了一个新随机 master 并用它存新 key。结果 8/5–8/6 用旧 master 加密的 3 条(阿里云百炼 / 智谱 / 硅基流动)永久不可解——旧 master 已无副本,64-hex 有 256 bit 熵,不可能爆破。

这 3 条没有被删除,而是标记 "legacy": true 保留:

清理办法:到对应平台重新获取 key → 让我 add 重存 → delete 掉 legacy 条目。

铁律:.env 缺失时绝不擅自新建 master。 正确顺序是——先看 vault.json 是否已有条目;有则立刻停手并索要原 master;确为空库才可生成新的,并把 64-hex 明确交给坤哥备份。重建前必须先备份现有 vault.json。

5. 命令与同步

# 存入
node ~/.workbuddy/skills/account-vault/vault.js add "服务名" "密钥值" "描述"
# 查询(脱敏 + 明文)
node ~/.workbuddy/skills/account-vault/vault.js get 关键词
# 取明文(谨慎)
node ~/.workbuddy/skills/account-vault/vault.js raw 服务名
# 列表 / 删除
node ~/.workbuddy/skills/account-vault/vault.js list
node ~/.workbuddy/skills/account-vault/vault.js delete 服务名

# 同步到线上(打包密文 + 页面 → tar over SSH → ECS)
cd ~/.workbuddy/skills/account-vault && bash sync-accounts.sh

同步脚本内置防泄漏校验:推送后回查服务端 vault.json,命中 sk- 等明文特征会告警。

网页端源码在 ~/.workbuddy/skills/account-vault/web/(index.html / app.js / vault.json),是唯一源,改完必须跑同步脚本,不要直接改 ECS 上的文件。

6. 安全说明

7. 后续可做

8. master 三点冗余机制 2026-08-07 新增

设计出发点很直接:坤哥不接受「自己另存到钥匙串/备忘录,需要时自己去翻」的方案——那等于把负担推回给人,和做这套系统的初衷相反。备忘录按时间排序,几个月后照样得翻半天,本质上没解决问题。

所以正确解法不是让人去记,而是让口令本身不会丢。由 scripts/master-guard.sh 在三个物理位置维护副本:

位置路径特点
[A] 主位~/.workbuddy/skills/account-vault/.env技能实际读取处;重装技能有被覆盖风险
[B] 本地独立位~/.vault-keys/master.key不随技能目录走,权限 600
[C] 异地位ECS /root/.vault-backup/master.key在 web 根之外,无任何 URL 可达,权限 600

加密数据 vault.json 同时备份到 ECS /root/.vault-backup/data/,保留最近 7 份——只有口令没有数据同样无用。

行为规则

命令

bash scripts/master-guard.sh            # 自检 + 自愈 + 数据备份
bash scripts/master-guard.sh --show     # 只打印当前 master
bash scripts/master-guard.sh --status   # 只体检不改动
已通过灾难演练验证:删除主位 .env 后运行守护脚本,口令从副本自动恢复,vault.js get deepseek 正常解出明文。
关于 [C] 位的安全权衡:异地副本与公开的 accounts/vault.json 在同一台 ECS 上。这是刻意选择——实际威胁模型是「自己弄丢文件」而非「服务器被攻破」,故优先保可用性。副本置于 /root/ 下(web 根之外 + 权限 600),即使 Nginx 配置出错也不会被 HTTP 暴露。若日后威胁模型改变,可把 [C] 换成独立的第三方存储。