本
本地 DPAPI 免口令凭据库(Windows)
作者:注册老炮@MedXpert I SynomosAIv1
用 Windows DPAPI 把密钥/口令加密存到本机、仅当前用户可解、明文不落盘、带权限锁与泄漏标注的可复用凭据保管 skill。适合"当前 Windows 账号即信任边界"的本地保管场景。
下载量
273
点赞
67
价格
免费
技能文档
--- name: dpapi-local-vault slug: dpapi-local-vault displayName: 本地 DPAPI 免口令凭据库(Windows) description: 用 Windows DPAPI 把密钥/口令加密存到本机、仅当前用户可解、明文不落盘、带权限锁与泄漏标注的可复用凭据保管 skill。适合"当前 Windows 账号即信任边界"的本地保管场景。 version: "1.1.0" license: MIT platforms: [Windows] author: 潘布达 (Buda Pan) @SynomosAI category: it-ops-security tags: [凭据管理, DPAPI, 本地加密, 免口令, Windows, 密钥保管] agent_created: true title: 本地 DPAPI 免口令凭据库(Windows) display_name: 本地 DPAPI 免口令凭据库(Windows) --- # 本地 DPAPI 免口令凭据库(Windows) ## 何时用 - 需要在**本机**安全保管一把密钥/口令(如云 API 密钥对、token),且信任边界就是"当前 Windows 登录用户"。 - 想要**免口令**体验:DPAPI 由系统用当前用户凭据透明加解密,无需记忆主口令。 - 不想把明文写进任何文件/日志/云文档;落盘只有 DPAPI 密文 + base64 封装。 - 需要给凭据打**泄漏标注**(如"已在聊天明文暴露、待轮换"),供后续取用前警告。 ## 何时不用 - 跨设备/跨账号同步 → 用 `unified-credential-vault`(带主口令、可恢复、全生态同读)。 - 需要多人共享或换机可解 → DPAPI 绑定本机本用户,换机/换账号解不开。 - 极高密级且担心"同账号被拖" → DPAPI 仅防其他用户/其他机,同账号可读,应上主口令保险库。 ## 用法 默认保险库目录:`~/.ucvault_local`(即 `C:\Users\<你>\.ucvault_local`)。 ### 推荐入口:key_drop.py(密值不进命令行、不进历史) `~/.ucvault_local/tools/key_drop.py`。三种模式,都不把密值写进命令行参数: ```bash # 1) 单值,隐藏输入(Git Bash / 支持 tty 的终端) python ~/.ucvault_local/tools/key_drop.py hunyuan_api_key # 2) 成对密钥对(如云 SecretId + SecretKey) python ~/.ucvault_local/tools/key_drop.py tencent_cos --pair # 3) 记事本模式(最保险,任何终端都能用,密值走 GUI 不经过终端) python ~/.ucvault_local/tools/key_drop.py tencent_cos --pair --notepad ``` - **模式 3 是最稳的**:不依赖终端能力,密值只经过记事本,导入后临时文件立即删除。 终端不支持隐藏输入、或旁边有人/在录屏时,一律用它。 - `vault put <label>`(vault.py 自带)只能存**单值**,存不了 SecretId+SecretKey 成对——成对请用 key_drop `--pair`。 - ⚠️ 坑:`getpass.getpass()` 在**无 tty** 环境(管道、CI、部分 Windows 终端)不会抛异常, 而是挂等 `/dev/tty` 导致命令卡死。先判 `sys.stdin.isatty()` 再决定走 getpass, 否则退回 `stdin.readline()` 并明确警告用户"输入会显示"。 ### 兜底:直接调 store_secret.py(heredoc) ⚠️ heredoc 里的密值会进终端回滚缓冲区与屏幕,仅在无法用 key_drop 时采用: ```bash python store_secret.py tencent_cos --scope secret --notes "腾讯云COS" \ --exposed --exposed-where "WorkBuddy聊天" --exposed-at "2026-08-28" <<'EOF' AKIDxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxKEY EOF # 两行 = 密钥对(SecretId / SecretKey);单行 = 单值 # 输出 STORED_OK 即成功(回环校验通过,不打印明文) ``` - 落盘:`~/.ucvault_local/<label>.enc`(DPAPI 密文)+ `<label>.meta.json`(作用域/泄漏标注)。 - 权限:`icacls /inheritance:r /grant:r <USER>:F` + `chmod 600`,仅当前用户可读。 ### 取回 ```bash python get_secret.py tencent_cos # 默认隐藏密值(安全展示) python get_secret.py tencent_cos --show # 显示明文(格式化输出,带 value:/secret_id: 标签前缀) python get_secret.py tencent_cos --raw # 只输出裸值(脚本/管道用,2026-09-07 新增) ``` ⚠️ **前缀坑(2026-09-07 实测教训)**:`--show` 输出是带 `value: ` / `secret_id:` 标签前缀的**格式化文本**,整段当令牌塞进 HTTP 头/URL,会得到大面积 401/40013 "令牌失效"假象——令牌其实是好的。**脚本取值一律用 `--raw`**;用 `--show` 必须 `sed -n 's/^value: *//p'` 截掉前缀。任何工具的人类可读输出都不能直接当凭据用。 ## 安全要点(落地约束) - **明文零落盘**:密钥只在 `CryptUnprotectData` 解密后的内存里短暂存在;文件里永远是 DPAPI 密文。 - **不回显**:`get_secret.py` 默认隐藏密值,`--show` 才显;store 的回环校验不打印明文。 - **密钥不进命令行**:密值走 stdin(heredoc),绝不用命令行参数传,防 `ps`/历史泄漏。 - **权限锁当前用户**:写入后立即去继承 + 仅授权当前用户完全控制。 - **泄漏标注**:`--exposed` 会在 meta.json 写 `EXPOSED_PENDING_ROTATION` + 暴露位置/时间,取用前先看到警告。 ## 配套文件 - `store_secret.py` — 加密写入(读 stdin;两行=密钥对,单行=单值;可选泄漏标注)。 - `get_secret.py` — 解密取回(默认隐藏密值,`--show` 才显明文)。 - `tools/key_drop.py` — **推荐投递入口**:隐藏输入 / 成对 / 记事本三种模式。 - `vault.py` / `vault.cmd` — 薄封装(`put`/`get`/`list`/`rm`);`put` 仅支持单值。 ## 应用侧读取约定(三级兜底) 应用不要自己解析 `.enc`,统一按此优先级取,改轮换只需换源头、不动代码: ``` 1. 环境变量 服务器部署 / CI 2. 本机保险库 ~/.ucvault_local(DPAPI) 3. 项目内文件 .llm_key / .cos.conf(仅兜底) ``` 参考实现见 `medxpert-reg-mcp/cred.py`(`llm_key()` / `cos_cred()`,通过 `get_secret.py --show` 取字段,只取长度/布尔判断,绝不打印密值)。 要点:取密值的代码**永远不要 print 密值**,也不要把它写进日志或异常信息。 ## 真实案例 本机保险库 `~/.ucvault_local/tencent_cos.enc`(Windows 即 `%USERPROFILE%\.ucvault_local\tencent_cos.enc`)即此法保管的一把腾讯云 COS 密钥(root 级,已标注 EXPOSED_PENDING_ROTATION,待用户在 CAM 禁用/轮换)。 --- ## 退出码与错误输出 | 场景 | 输出 | 退出码 | 处置 | |---|---|---|---| | 取回时 label 不存在 | `NOT_FOUND: <vault路径>` | 2 | 先用 store_secret.py 写入,或核对 label 拼写 | | 写入时 stdin 为空 | `MISSING_INPUT` | 2 | 检查管道输入:两行 = id+key,一行 = 单值 | | 跨机器/换用户解密失败 | DPAPI 异常(非零退出) | ≠0 | DPAPI 绑定当前 Windows 用户+机器;跨机需提前导出,未导出不可恢复(设计内行为) | | --show 与 --raw 混淆 | --show 输出带 `value: ` 前缀(人读格式) | 0 | 脚本取值必须用 `--raw`(裸值),禁止对 --show 输出做字符串截取 | ## 反模式 FAQ **Q:换电脑/重装系统后解不开了,是 bug 吗?** 不是,是设计内行为。DPAPI 绑定当前 Windows 用户+机器;跨机迁移必须提前导出,没导出就不可恢复。 **Q:能把保险库目录放进网盘同步吗?** 密文 blob 可以同步做灾备存档,但跨机器解不开(见上条)。别指望网盘当跨机传输通道。 **Q:--show 输出直接给脚本解析为什么出错?** --show 是人读格式,带 `value: ` 前缀;脚本取值必须用 --raw。禁止对 --show 输出做字符串截取。 **Q:多脚本并发读写同一凭据安全吗?** 读操作无竞争;写操作(store/rotate)要串行,轮换时先禁用旧 key 再写入新 key。 ## 版权与许可 - © 2026 SynomosAI。本技能按 MIT 许可证开源(见 LICENSE.md);软件依 LICENSE 使用,零数据收集。 - **知识版权声明**:本作品汇集的方法论、协议流程与结构化知识,其编排与原创表达归 SynomosAI 所有;未经书面许可,不得复制、转载、摘编、转售或用于训练任何模型 / 商业系统。 - **免责声明**:本作品按「现状」(AS IS)提供,不提供任何明示或暗示担保;使用风险由使用者自行承担,因使用所致任何损失作者不承担责任。 ## 安装与使用矩阵 | 宿主 | 安装位置 | 方式 | |---|---|---| | Claude Code / CodeBuddy | `~/.claude/skills/dpapi-local-vault/` | 复制本目录即可 | | OpenCode | `~/.config/opencode/skills/dpapi-local-vault/` | 复制本目录即可 | | 通用 Agent Skill 加载器 | `~/.agents/skills/dpapi-local-vault/` | 复制本目录即可 | --- [](https://medxpert.cn) > © 2026 SynomosAI(诺声 Logos 署名体系)· MIT License · 按现状(AS IS)提供,不作任何明示或暗示担保
支持平台:Qoder · QoderWork · Claude · Codex 等 AI 编程助手