kdbx-wasm 是一个用 Rust 编写、编译到 WebAssembly 的 KDBX 4 密码数据库解析器,同一份包可以直接跑在浏览器和 Node.js 里,用来读写 KeePass 的 .kdbx 文件。
特性
- KDBX 4:解析、修改并导出
.kdbx文件(不支持 3.x 旧格式) - 加密算法:AES-256-CBC / ChaCha20
- 密钥派生:Argon2d / Argon2id / AES-KDF
- 零依赖:独立发布,无需任何原生 addon
- TypeScript:完整类型定义,开箱即用
- 密码默认不出现在查询结果里,需显式传入参数才会返回
支持的 KeePass 特性
| 特性 | 状态 |
|---|---|
| AES-256 / ChaCha20 加密 | ✅ |
| Argon2d / Argon2id / AES-KDF | ✅ |
| Gzip 压缩 | ✅ |
| 分组与条目 | ✅ |
| 自定义字段 | ✅(普通 Object) |
| 条目历史 | ✅(往返保留) |
| 二进制附件 | ✅(往返保留,含引用) |
| 标签 | ✅ |
| 密码 + 密钥文件 | ✅(原始 / XML v1/v2 / hex) |
安装
npm install kdbx-wasm
Node.js 需要 19+(仅 ESM,随机数依赖全局 crypto);Node 18 上需自行 polyfill globalThis.crypto。
快速上手
Node.js
WASM 模块在 import 时同步加载,无需调用 init():
import { readFileSync } from 'node:fs';
import { KdbxDatabase, isKdbxFile, getFileInfo } from 'kdbx-wasm';
const data = new Uint8Array(readFileSync('passwords.kdbx'));
// 快速校验
if (!isKdbxFile(data)) throw new Error('Not a valid KDBX file');
// 不解密即可窥探头部信息
const info = getFileInfo(data);
console.log(info.encryptionAlgorithm); // "AES-256"
console.log(info.kdfAlgorithm); // "Argon2id"
// 打开数据库
const db = new KdbxDatabase(data, 'master-password');
// 列出所有条目(默认不含密码)
for (const entry of db.getEntries()) {
console.log(entry.title, '-', entry.username);
}
// 导出(可换主密码)
writeFileSync('exported.kdbx', db.toBytes('new-password'));
浏览器
浏览器端 WASM 异步加载,首次使用前调用一次默认导出的 init():
import init, { KdbxDatabase, isKdbxFile } from 'kdbx-wasm';
await init();
const data = new Uint8Array(await file.arrayBuffer());
if (isKdbxFile(data)) {
const db = new KdbxDatabase(data, 'master-password');
for (const entry of db.getEntries()) {
console.log(entry.title, entry.username);
}
}
包的 exports 字段会自动按环境路由:Node 走同步加载入口,浏览器 / 打包器走 fetch 版入口。
常用操作
// 全文搜索(标题、用户名、URL、备注、标签、自定义字段值)
const results = db.searchEntries('github');
// 创建 / 修改条目
const uuid = db.createEntry(groupUuid, 'New Service', 'generated-password');
db.setEntryUsername(uuid, 'newuser');
db.setEntryCustomField(uuid, 'OTP', '123456');
// 分组操作
const groupId = db.createGroup('Work', db.rootGroupUuid);
db.moveEntry(uuid, groupId);
// 到期时间(RFC 3339)
db.setEntryExpires(uuid, '2026-12-31T23:59:59Z');
条目历史、二进制附件(含引用)在往返读写中都会完整保留;导出的文件可能比原文件略小,这是未保留的 KeePass 内部冗余数据(如未使用的自定义图标)所致,属正常现象。
安全设计
- 所有密码学运算(AES、ChaCha20、Argon2、HMAC)都在 WASM 沙箱内完成;
- 查询结果默认剥离密码字段,必须显式请求才返回;
- Rust 侧
SecString/SecVec使用zeroize在丢弃时清零内存。
从源码构建
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli
./scripts/build-wasm.sh