1. 为什么我要用 Codex 手搓一个本地密码管理器
浏览器里存着几十个账号,每次登录都要翻备忘录;用在线密码工具又担心数据被同步到不知道哪台服务器上。这个场景你应该不陌生。我这次想做的事情很直接:用 Codex 从零生成一个纯本地的密码管理器,所有数据只留在自己的浏览器里,主密码派生密钥、AES-256-GCM 加密存储、随机密码自动生成,一条龙跑通。
核心检索词先摆出来:Codex 本地密码管理器、AES 加密存储、主密码派生密钥、随机密码自动生成。它是什么?就是一个跑在浏览器里的单页应用,用 Web Crypto API 做加密,用 localStorage 做持久化,不依赖任何后端。能做什么?保存网站/邮箱/银行/社交账号的密码,一键生成强密码,实时评估强度,加密导出备份。适合谁?想练手 Codex 生成完整项目的前端同学、对密码安全有基本要求但不想把数据交给第三方的普通用户、以及想理解 AES-GCM 和 PBKDF2 怎么在浏览器里落地的人。
整个项目我拆成四层:crypto.js 负责加解密和密钥派生,storage.js 负责数据读写和自动锁定,generator.js 负责密码生成,app.js 负责 UI 串联。下面每一步的提示词和生成结果我都会贴出来,你可以直接复制去跑。环境上只需要 Node 20+ 和最新版 Codex CLI,先确认一下:
node -v # v20.16.0 codex --version # codex-cli 0.9.x这里有个前提说明:本项目用 Web Crypto API 的 AES-256-GCM,这是浏览器原生提供的加密能力,数据不经过任何服务器。但生产环境还是建议用 Bitwarden、1Password 这类成熟工具,我们做的是教学和自用场景。
2. TaoToken 统一 Key 与 API 通道的前置准备
Codex 在生成代码的过程中会频繁调用模型,如果你本地没有稳定的 API 通道,生成到一半断掉会非常难受。我自己的做法是走 TaoToken 的统一 Key 通道,把模型调用集中管理,Codex 侧只需要配置一个 Base URL 和一个 Key。
TaoToken 是什么?它是一个统一的模型 API 接入层,把不同模型的调用收敛到同一个入口,适合 Codex、Cline、Claude Code 这类编码工具长期使用。官网入口在这里:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api ,注意 API 地址后面不加 UTM 参数。
你需要准备三件套:Base URL、API Key、Model ID。Base URL 填https://taotoken.net/api,API Key 在控制台的 API Keys 页面创建,Model ID 根据你用的模型填,比如claude-sonnet-4-20250514或gpt-4o这类。创建 Key 的入口在 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite ,接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_content=doc&utm_campaign=rewrite 。
如果你用的是 Claude Code 做润色或补全,配置方式类似,参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 。长期做编码和 Agent 任务的话,Coding Plan 会更划算,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。
配置好之后,Codex 的请求就会走这条通道。我实测下来,生成一个完整项目大概需要十几轮对话,通道稳定的话基本不会中断。这里要提醒一句:不要把生产数据库的直连信息塞进 MCP 配置里,我们只做本地文件生成,不碰任何线上数据。
3. 可复制的项目结构与加密模块配置
先让 Codex 初始化项目骨架。提示词我写得很具体,把文件结构和加密要求都列清楚:
codex "创建本地密码管理器项目 password-vault。文件结构: - index.html - css/style.css - js/crypto.js AES-256 加解密模块 - js/storage.js 加密数据存储 - js/generator.js 密码生成器 - js/app.js 主入口 先创建加密模块,使用 Web Crypto API 实现: 1. PBKDF2 从主密码派生 256 位密钥 2. AES-256-GCM 加密/解密函数 3. 主密码哈希验证 所有注释用中文"Codex 执行后会生成js/crypto.js,核心配置我贴出来,你可以对照检查:
const CRYPTO_CONFIG = { ALGORITHM: 'AES-GCM', KEY_LENGTH: 256, IV_LENGTH: 12, SALT_LENGTH: 16, ITERATIONS: 600000, HASH: 'SHA-256' }; async function deriveKey(masterPassword, salt) { const encoder = new TextEncoder(); const keyMaterial = await crypto.subtle.importKey( 'raw', encoder.encode(masterPassword), 'PBKDF2', false, ['deriveKey'] ); return crypto.subtle.deriveKey( { name: 'PBKDF2', salt: salt, iterations: CRYPTO_CONFIG.ITERATIONS, hash: CRYPTO_CONFIG.HASH }, keyMaterial, { name: CRYPTO_CONFIG.ALGORITHM, length: CRYPTO_CONFIG.KEY_LENGTH }, false, ['encrypt', 'decrypt'] ); }加密函数把 salt、IV、密文拼成一个字节数组再转 Base64,解密时按固定长度切回来。这里的关键参数是ITERATIONS: 600000,PBKDF2 迭代次数越高,暴力破解成本越大,但派生密钥也越慢。600000 是当前比较推荐的平衡值,实测在普通笔记本上派生一次大约 200-400ms,用户感知不明显。
如果你用 TOML 或 JSON 管理配置,可以这样写:
{ "crypto": { "algorithm": "AES-GCM", "keyLength": 256, "ivLength": 12, "saltLength": 16, "iterations": 600000, "hash": "SHA-256" }, "autoLockMinutes": 5 }注意deriveKey的最后一个参数是['encrypt', 'decrypt'],不要写成['encrypt'],否则解密会报InvalidAccessError。另外extractable设为false,密钥不可导出,安全性更高。
4. 验证请求与三步跑通加密写入、解密读取、生成强度校验
代码生成完,怎么确认它真的能跑?我设计了三个验证动作,你按顺序做一遍。
第一步,加密写入。打开浏览器控制台,手动调用一次:
const salt = generateRandomBytes(16); const key = await deriveKey('MyMasterPass123!', salt); const encrypted = await encryptData('hello-vault', 'MyMasterPass123!'); console.log('加密结果:', encrypted); // 输出类似: "3q2+7wAAAAB...base64..."如果控制台返回一串 Base64 字符串,说明加密链路通了。这里注意encryptData内部会自己生成 salt 和 IV,所以不需要你手动传。
第二步,解密读取。把上一步的密文传回去:
const decrypted = await decryptData(encrypted, 'MyMasterPass123!'); console.log('解密结果:', decrypted); // 输出: "hello-vault"如果输出hello-vault,说明加解密闭环成立。故意传错主密码,应该抛出解密失败:主密码不正确,这是 AES-GCM 的认证标签校验在起作用。
第三步,生成强度校验。调用生成器生成一个 20 位密码,再评估强度:
const pw = generatePassword({ length: 20, lowercase: true, uppercase: true, digits: true, special: true }); console.log('生成密码:', pw); const strength = evaluatePasswordStrength(pw); console.log('强度:', strength.label, '得分:', strength.score); // 强度: 极强 得分: 4三步都通过后,打开index.html,设置主密码,添加一条记录,刷新页面,再用主密码解锁,数据应该还在。这一步验证的是 localStorage 持久化和主密码哈希校验。如果刷新后数据丢失,检查saveVault是否在addEntry之后被调用。
5. 本篇常见错误排查:401、local proxy failed、reading choices、OAuth
生成和运行过程中我踩过几个坑,对照着看能省不少时间。
401 Unauthorized:Codex 调用模型时返回 401,通常是 API Key 没配或配错。检查~/.codex/config.toml里的api_key字段,确认 Key 没有多余空格。如果你走 TaoToken 通道,Base URL 要填https://taotoken.net/api,不要漏掉/api路径。
local proxy failed:本地代理启动失败,一般是端口被占用或代理配置指向了不存在的地址。先确认没有其他进程占用 Codex 默认端口,再检查配置文件里的base_url是否可达。可以用curl https://taotoken.net/api/models测试连通性。
reading choices 报错:模型返回结构里没有choices字段,通常是请求体格式不对或模型 ID 写错。检查 Model ID 是否拼写正确,比如claude-sonnet-4-20250514不要写成claude-sonnet-4。另外确认请求头Content-Type: application/json没丢。
OAuth 相关报错:如果你用 Claude Code 的 OAuth 流程,报OAuth token expired时重新走一遍授权即可。参考 https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_content=claudecode&utm_campaign=rewrite 里的配置说明,Base URL、Key、Model ID 三件套要写全。
还有一个容易忽略的点:crypto.subtle只在 HTTPS 或 localhost 下可用。如果你用file://协议直接打开index.html,crypto.subtle会是undefined。解决办法是用npx serve或python -m http.server起一个本地服务,访问http://localhost:3000。
6. 继续用 Codex 扩展你的密码管理器
跑通基础版本后,你可以继续让 Codex 加功能。比如自动锁定,提示词写「监听页面可见性变化,切到其他标签页时隐藏所有已显示的密码,5 分钟无操作自动锁定」。Codex 会在app.js里加上visibilitychange和blur事件监听。
再比如加密导出,提示词写「导出时用当前主密码重新加密整个 vault,生成 JSON 文件下载;导入时用导出时的主密码解密,按标题+用户名去重合并」。这样备份文件即使泄露,没有主密码也解不开。
如果你想把模型调用也统一管理,可以在 Codex 配置里把 Base URL 指向 https://taotoken.net/api ,Key 用 https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api_keys&utm_campaign=rewrite 创建的,Model ID 按需选。需要验证模型效果时,可以用 https://taotoken.net/model-chat?utm_source=taotoken_aicg_blog_end&utm_content=model_chat&utm_campaign=rewrite 快速对话测试。长期做编码任务的话,Coding Plan 入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding_plan&utm_campaign=rewrite 。
最后提醒一句:这个项目是教学性质的本地工具,主密码一旦忘记无法找回,因为密钥是从主密码派生的,没有后门。生产环境请用成熟密码管理器。你现在就可以打开终端,把第 3 节的提示词复制进去,让 Codex 开始生成。