Skip to content

About

Verify a directory tree against an XXH3-128 manifest — detects deleted, added, modified and retyped files and directories. no platform APIs.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

10 Commits

Folders and files

Repository files navigation

目录完整性校验

使用 Rust + iced 原生实现的跨平台 GUI 工具,用于生成目录摘要,并根据摘要检查目录中的文件或子目录是否被增加、删除、修改或改变类型。

目录遍历、XXH3-128 流式哈希、摘要解析、自校验和差异比对全部由 Rust 实现,不调用归档的 C/C++ 代码。

另提供可部署到 Cloudflare Pages 的浏览器版本:本地文件由 Rust WASM 分块摘要,摘要文本交给 Cloudflare Worker 使用 Ed25519 私钥签名。部署、安全边界和使用说明见 cloudflare/README.md。

功能

  • 读取摘要文件:选择已有的 .dirverify 摘要并显示。
  • 生成摘要文件:选择目录后扫描普通文件和所有子目录,包括空目录。
  • 生成签名密钥:使用操作系统安全随机数生成 Ed25519 私钥和公钥。
  • 根据摘要验证目录:使用当前显示的摘要检查所选目录,结果通过弹窗显示。
  • Ctrl+S 保存并签名:选择 ZIP 路径和私钥,生成与 Web 版一致的“目录名.dirverify.sign.zip”,其中包含摘要和签名两个文件。
  • 摘要显示区域不自动换行;内容超出宽度或高度时自动提供水平、垂直滚动条。
  • 扫描和校验使用 iced 后台任务,操作期间会暂时禁用按钮。

校验结果

程序明确区分三种结论:

校验通过    目录内容与摘要一致
校验失败    发现缺失、新增、修改或类型变化
校验未完成  存在无法读取的路径,本次结果不可信

“无法读取”和“没有变化”不会被混淆。即使未完成的扫描同时发现了一些差异,最终结论仍是“校验未完成”。

签名 ZIP 可以保存在被校验目录内。生成后保存或执行校验时,程序会自动排除该 ZIP,避免把它记录进摘要或误报为新增文件。读取旧式摘要时仍兼容相邻的 .dirverify 和 .dirverify.sign 两个文件。

读取摘要和执行目录校验都强制验证 Ed25519 签名。签名文件缺失、签名无效、公钥不匹配或磁盘摘要在读取后发生变化时,程序会拒绝继续校验。

构建与运行

需要 Rust 1.88 或更高版本。

cargo run --release

仅构建:

cargo build --release

产物位置:

  • Linux/macOS:target/release/dir_integrity_check
  • Windows:target\release\dir_integrity_check.exe

Linux 使用 XDG Desktop Portal 打开文件和目录选择对话框。常见 GNOME、KDE 桌面通常已安装对应后端;精简桌面环境可以安装 zenity 作为回退。

使用方法

生成摘要

  1. 首次使用时点击“生成签名密钥”,分别保存私钥和公钥。
  2. 把私钥放在安全位置;不要放入被校验目录,也不要交给验证方。
  3. 点击“生成摘要文件”,选择需要生成摘要的目录。
  4. 等待摘要内容显示完成。
  5. 按 Ctrl+S 选择 ZIP 保存路径,然后选择用于签名的私钥。

假设选择的目录是:

/data/example

默认保存路径为:

/data/example.dirverify.sign.zip

ZIP 内包含:

example.dirverify
example.dirverify.sign

需要在以后重新读取该摘要时,先解压 ZIP,再通过“读取摘要文件”选择其中的 .dirverify;程序会读取同目录下对应的 .dirverify.sign。

校验目录

  1. 确保 .dirverify 和对应的 .dirverify.sign 位于同一目录。
  2. 点击“读取摘要文件”,选择摘要。
  3. 选择来自可信来源的 Ed25519 公钥。签名无效或签名文件缺失时,摘要不会被载入。
  4. 点击最右侧的“根据摘要验证目录”。
  5. 程序再次读取摘要和签名并重新验证,然后才允许选择要检查的目录。
  6. 在弹窗中查看校验结论和具体差异。

刚生成但尚未保存签名 ZIP 的摘要不能用于目录校验。保存成功后,程序会在校验前重新读取 ZIP 内的摘要和签名并验签。

读取时找不到签名文件或公钥会提示“读取摘要失败,未找到签名”;签名格式无效、公钥不匹配或摘要被修改会提示“读取摘要失败,验签未通过”。

目录验证前的二次验签采用相同分类,分别提示“验证摘要失败,未找到签名”或“验证摘要失败,验签未通过”,并拒绝选择校验目录。

摘要格式

摘要继续使用 #dirverify 1 行式文本格式,与归档的 C++ 版本兼容:

#dirverify 1
#algo xxh3-128
#root example
#created 2026-07-30T00:00:00Z
#entries 2
d	0	-	empty
f	3	06b05ab6733a618578af5f94892f3950	a.txt
#trailer xxh3-128 ...
  • 条目按相对路径的 UTF-8 字节序排序。
  • 普通文件记录文件大小和 XXH3-128 内容摘要。
  • 目录是独立条目,因此可以检测空目录的增加和删除。
  • 路径中的反斜杠、换行、回车和制表符会被转义。
  • #trailer 覆盖前面的全部字节,可检测摘要截断或意外损坏。
  • 读取摘要时会先验证尾部摘要和条目数量,再执行目录校验。

Ed25519 签名

签名覆盖 .dirverify 文件的全部原始字节,签名文件格式为:

#dirverify-signature 1
#algorithm ed25519
#signature <128 位十六进制签名>

签名文件不内嵌公钥。验证时必须由用户选择可信公钥,防止攻击者同时替换摘要、签名和公钥。

生成的私钥文件在 Unix 系统上会设置为仅当前用户可读写(0600)。私钥仍是未加密文件,必须单独、安全地保管;公钥可以分发给验证方,建议通过可信渠道核对。

校验范围与限制

记录并校验:

  • 普通文件的内容摘要和大小
  • 目录,包括空目录

不记录:

  • 权限、时间戳、所有者
  • 符号链接
  • socket、FIFO 和设备文件

符号链接和特殊文件虽然不参与摘要,但扫描时会计数。遇到不可读文件、不可读目录或无法写入文本摘要的非 Unicode 路径时,程序不会给出“校验通过”的结论。

XXH3-128 用于高效检测目录内容变化,#trailer 用于发现摘要文件的意外损坏;两者都不是防伪机制。防篡改能力由 Ed25519 签名提供,其前提是私钥没有泄露,并且验证者选择的是可信公钥。

测试

cargo test --all-targets
cargo clippy --all-targets -- -D warnings

测试覆盖摘要往返解析、摘要损坏检测、旧 C++ 摘要兼容、签名 ZIP 读写、Ed25519 签名、签名缺失和篡改拒绝、目录差异分类、目录内输出排除和未完成扫描结论。

项目结构

.
├── Cargo.toml
├── Cargo.lock
├── src/
│   ├── main.rs       iced GUI、文件对话框和快捷键
│   ├── lib.rs        摘要生成、保存和校验入口
│   ├── archive.rs    摘要与签名 ZIP 的生成和严格读取
│   ├── manifest.rs   摘要序列化、解析和尾部自校验
│   ├── scanner.rs    Rust 原生目录遍历和文件哈希
│   ├── signature.rs  Ed25519 密钥、签名和严格验证
│   └── verifier.rs   差异比较、折叠和结果报告
├── cloudflare/
│   ├── wasm/         浏览器端 Rust WASM 摘要生成器
│   ├── worker/       Rust Ed25519 签名 Worker
│   └── web/          Cloudflare Pages 前端与 Service Binding
└── cpp_archive/      已归档、可独立构建的旧 C++ 版本

归档 C++ 版本的说明和 CMake 工程位于 cpp_archive/。

About

Verify a directory tree against an XXH3-128 manifest — detects deleted, added, modified and retyped files and directories. no platform APIs.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages