Skip to content

feat(tools): 新增真实 WCDB 加密的演示数据库种子脚本 - #153

Closed
magicapple123 wants to merge 1 commit into
LifeArchiveProject:mainfrom
magicapple123:feat/seed-demo-database
Closed

magicapple123 wants to merge 1 commit into
LifeArchiveProject:mainfrom
magicapple123:feat/seed-demo-database

Conversation

@magicapple123

Copy link
Copy Markdown

这个 PR 做了什么

新增一个演示数据库种子脚本,用于生成真正按 WCDB/SQLCipher 页格式加密的演示账号数据。

仓库里已有的 tools/seed_ai_acceptance.py 生成的是明文 SQLite,而真实链路是 WCDB
加密的 —— 从「扫描账号目录」到「解密」再到「读取」这一整段没有任何测试数据可以覆盖。
这个脚本补上这一段。

两个刻意的设计

1. 不硬编码加密常量,而是复用上游实现

脚本 import 上游自己的常量与函数,而不是复制一份魔数:

from wechat_decrypt_tool.wechat_decrypt import (
    HMAC_SIZE, IV_SIZE, PAGE_SIZE, RESERVE_SIZE, SALT_SIZE,
    _derive_mac_key, _derive_sqlcipher_enc_key,
)

我认为这一点比脚本本身更重要:如果将来页格式或密钥派生方式发生变化,
脚本会跟着一起失效(HMAC 校验不过),而不是悄悄产出一批看起来正常、
实际无法解密的数据。硬编码常量的写法在那种情况下会非常难排查。

2. 数据全是虚构的

wxid_demo_2026、昵称统一带「示例」、链接一律 example.com、群聊 10000000001@chatroom。
覆盖单聊/群聊与文本/链接卡片/转账/系统提示/引用消息(refermsg)多种消息类型。

用途是给测试、截图、文档、新贡献者上手提供一个不含任何真实隐私的起点 ——
我自己在做对外截图时最缺的就是这个,用真实数据截图是不可接受的。

自校验

脚本带 --check,用上游自己的解密器验证产出物,实测输出:

Page 1 HMAC verification passed: mode=sqlcipher_passphrase
successful_pages=7 failed_pages=0
reserved_space=80
quick_check: ok
table_count: 6
自校验通过:扫描到 5 个数据库,成功解密 2/2 个

涉及文件

+ tools/seed_demo_database.py        (465 行,脚本主体)
+ tests/test_seed_demo_database.py   (142 行,5 项测试)
+ docs/demo-database-seed.md         ( 91 行,中文文档)

没有修改任何既有文件(git diff --stat 确认 3 files changed, 698 insertions,
0 deletions),所以对现有行为零影响。

输出默认落在 output/demo/,该目录已在 .gitignore 中,因此不需要改动
ignore 规则、也不会污染工作区。

测试

tests/test_seed_demo_database.py 守的是「演示数据 == 真实解密链路」这个契约,5 项:

  • 逐页 HMAC 与上游 _compute_page_hmac 计算结果一致;
  • 解密后是合法 SQLite 且 quick_check 通过;
  • Name2Id 不含账号自己(否则聊天列表会把自己列出来);
  • 所有昵称都带「示例」标记(防止将来有人误用真实数据);
  • encrypt_wcdb 拒绝非 4096 对齐的输入。

关于完整测试集的对比,我在 #152 里说明过:基线 2682 项(85 失败 / 18 错误)→
本分支 2758 项,失败集合逐项比对完全相同,新增测试全部通过。
那些既存失败在本机是环境缺件(缺 wechatdb_client.dll 等)导致,与本 PR 无关。

关于许可证

顺带说明:这个 PR 是在与 #152 相同的疑问下提交的 —— 仓库当前没有 LICENSE 文件。
如果维护者认为在许可条款明确前不宜接受外部代码,直接关掉即可,我完全理解,
不会介意。许可证明确后我可以按需要重开。

后续

我在 fork 上还有一个多协议云端语音识别适配器(engine="cloud")分支已完成,
但因为 #151 正在改写同一片区域(voice_transcription.py 批量入口、
SettingsDialog.vue、VoiceTranscriptionSidebar.vue),我打算等 #151 合入后再 rebase 提交,
避免制造冲突。感兴趣的话可以先看 fork 上的 feat/cloud-asr-adapter 分支。

贡献者本地通常没有微信环境,也不应拿真实聊天记录做调试;已有的
tools/seed_ai_acceptance.py 生成的是明文 SQLite,只覆盖 AI 验收,
无法验证「密钥 -> 逐页 HMAC 校验 -> 解密 -> 解析」这条主链路。

新增 tools/seed_demo_database.py,生成完全虚构但真实加密的演示账号:
- 逐页 AES-CBC + 逐页 HMAC-SHA512,密钥派生复用上游 wechat_decrypt
  的常量与函数(PAGE_SIZE / RESERVE_SIZE / _derive_sqlcipher_enc_key /
  _derive_mac_key),上游调整页格式时脚本随之变化;
- 5 个会话 29 条消息,覆盖文字、链接卡片 / 转账卡片(含 refermsg 引用)、
  系统消息、表情与语音占位;
- Name2Id 不含账号本人,与真实微信结构一致,避免会话列表多出一条自己;
- 昵称统一带「示例」标记、域名 example.com,任何导出物都能一眼识别为虚构数据。

同时提供 --check 自校验:调用 scan_account_databases_from_path 与
decrypt_wechat_databases 走完整解密链路,逐页校验 HMAC,并检查解密后
PRAGMA integrity_check 与关键表是否存在。

回归测试 tests/test_seed_demo_database.py 守护「演示数据与真实解密链路一致」
这一契约,逐页比对 HMAC 与 _compute_page_hmac 的结果。

实测:--check 输出「成功解密 2/2 个」,上游解密器日志打印
Page 1 HMAC verification passed: mode=sqlcipher_passphrase,
successful_pages=7 failed_pages=0,reserved_space=80。

默认输出到 output/demo,已被 /output/ 规则忽略,不进入版本库;
脚本只写 --output 指定目录,不读取也不修改任何真实微信目录。
@2977094657 2977094657 closed this Sep 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants