kylemaps/veriseal

GitHub: kylemaps/veriseal

一款对机器人/自动驾驶 MCAP 日志进行 Ed25519 签名和 Bitcoin 时间戳锚定的防篡改封装与独立验证工具。

Stars: 0 | Forks: 0

# veriseal 专为需要在事后证明机器人/自主驾驶日志未被篡改的事故调查员和安全团队打造。 这是一个 CLI 工具,它使用 Ed25519 签名和 Bitcoin 时间戳 (OpenTimestamps) 对机器人/自主驾驶日志 (MCAP) 进行封装,并生成一个 `.seal.json` 清单。无关第三方随后可以证明“此日志与由密钥 K 创建、并在时间 T 锚定的时间戳封装记录相符”——但前提是验证者**固定了签名者的公钥** (`--pubkey`)。如果不固定公钥,使用新密钥篡改并重新封装的日志依然能通过验证。 ![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg) ![演示](https://static.pigsec.cn/wp-content/uploads/repos/cas/6e/6e9604b85998c5fd026570015bf4a18d16c58d94baa5ca1face717c3fd7af920.gif) ## 安装 ``` pip install git+https://github.com/kylemaps/veriseal ``` 或者用于开发: ``` git clone https://github.com/kylemaps/veriseal.git cd veriseal pip install -e . ``` ## 快速开始 ``` # 封装日志(生成新的密钥;默认将 Merkle root 提交到 OpenTimestamps) veriseal seal log.mcap --out log.seal.json # 不使用 OpenTimestamps 进行封装 — 快速,完全离线 veriseal seal log.mcap --no-anchor --out log.seal.json # 验证完整性(警告:如果不使用 --pubkey,嵌入的密钥将被无条件信任) veriseal verify log.mcap log.seal.json # INTACT — 签名有效,198 条消息,root 9bfe72f8a52c5ad5... # 警告:未提供 --pubkey:信任嵌入在 manifest 中的密钥;... # 验证并固定签名者的密钥 — 唯一能检测篡改重新封装的方法 veriseal verify log.mcap log.seal.json --pubkey signer.pub.pem # INTACT — 签名有效,198 条消息,root 9bfe72f8a52c5ad5... # 篡改检测 — 在副本中翻转一个字节并重新验证 python -c " d = bytearray(open('log.mcap', 'rb').read()) d[1024] ^= 0xFF open('tampered.mcap', 'wb').write(bytes(d)) " veriseal verify tampered.mcap log.seal.json --pubkey signer.pub.pem # TAMPERED # Source digest 不匹配 # 预期 9bfe72f8a52c5ad5... # 实际 0816a35ad0908c74... # Merkle root 不匹配 # 预期 9bfe72f8a52c5ad5... # 实际 3f4a2b1c8e9d6f7a... # MODIFIED topic='/pose' log_time=1750032000000000000 # 检查事件的 incident 时间窗口(ISO-8601 或自 epoch 以来的纳秒数) veriseal inspect log.mcap \ --from 2025-06-16T00:00:01Z \ --to 2025-06-16T00:00:04Z \ --topic /pose # 将时间窗口导出为新的 MCAP(可在 Foxglove Studio 中打开) veriseal inspect log.mcap \ --from 2025-06-16T00:00:01Z \ --to 2025-06-16T00:00:04Z \ --out incident.mcap ``` ### OpenTimestamps 锚点 默认情况下,`veriseal seal` 会将已签名的 Merkle root 提交到公共 Bitcoin 日历服务器 ([OpenTimestamps](https://opentimestamps.org))。内嵌的证明初始状态为 `status: "pending"`,一旦 Bitcoin 区块包含该 Merkle 路径(大约 1 小时后),状态就会变为 `"confirmed"`。 `veriseal verify` 会报告锚点状态作为**信息参考** —— 除非设置了 `--require-anchor`,否则 INTACT/TAMPERED 的验证结果和退出代码不会受锚点状态的影响: ``` INTACT — signature valid, 198 messages, root 9bfe72f8a52c5ad5... Anchor: pending (not yet Bitcoin-confirmed) ``` 在离线工作流或 CI 中跳过锚定: ``` veriseal seal log.mcap --no-anchor ``` 要求有效的锚点(在审计流水线中非常有用): ``` veriseal verify log.mcap log.seal.json --pubkey signer.pub.pem --require-anchor ``` ### ROS 1 rosbags veriseal 封装的是 MCAP;它不直接读取 ROS 1 的 `.bag` 文件。请先进行转换,然后再封装 —— 详见 [docs/ros1.md](docs/ros1.md)。 ## 威胁模型 **它能证明什么:** 此日志与由密钥 K 在时间 T 创建的封装记录相符。“独立可验证”需要两个条件:(1) 验证者知道并固定了签名者的公钥 (`--pubkey`);(2) 锚点是可信的。如果没有 `--pubkey`,使用新密钥篡改并重新封装的日志依然能通过验证。如果没有锚点,时间声明仅仅依赖于封装者的单方面主张。 **它不能证明什么:** 日志是捕获时刻物理真实情况的真实记录。封装操作无法复原被伪造的数据。完整性 ≠ 真实性。 **中立性的真正来源:** 尽可能早地进行封装(最好在捕获时或接近捕获时),并将 root 锚定到公共的仅追加日志中,这样任何单方(包括托管者)都无法将其倒填日期或篡改。封装时间越接近捕获时间且锚点越公开,证据的“中立性”就越强。 ## 工作原理 1. **Hash** — 每个 MCAP 消息都经过域分离并进行 SHA-256 哈希处理:`SHA-256(b"\x00" + b"veriseal-leaf-v1\x00" + len(topic) + topic + log_time + payload)`。 2. **Merkle tree** — 叶子节点按 `(log_time, topic, leaf_hash)` 排序,并使用 [RFC 6962](https://www.rfc-editor.org/rfc/rfc6962) 二进制 Merkle Tree Hash 算法进行组合。任何单字节的更改都会改变 root;通过叶子节点的差异可以精准定位受影响的 (topic, log_time) 组。 3. **Sign** — 清单(root + 所有叶子节点 + 元数据)被序列化为规范化的 JSON,并使用 Ed25519 进行签名。签名者的公钥会内嵌在清单中。 4. **Anchor** — 已签名的清单经过 SHA-256 哈希处理,并提交给 [OpenTimestamps](https://opentimestamps.org) 公共日历。随后的 Bitcoin 区块会对其进行确认,从而提供一个任何单方(包括封装者)都无法倒签日期的去信任时间戳。 `.seal.json` 格式在 **[SPEC-manifest.md](SPEC-manifest.md)** 中有完整记录 —— 一个合规的验证器只需要该文档、MCAP 以及标准加密库。 ## 架构 ``` seal ingest MCAP → hash every message → RFC 6962 Merkle tree → sign manifest (Ed25519) → anchor root (OpenTimestamps/Bitcoin) → *.seal.json verify recompute Merkle tree from MCAP → check signature → compare roots → INTACT or TAMPERED (locate modified/added/removed messages) informational: anchor status (pending / confirmed / invalid) optional: --pubkey to pin the signer's key, --require-anchor to enforce anchor inspect filter MCAP to time window → print chronological event timeline → export window as incident.mcap (openable in Foxglove Studio) ``` ## 运行演示 ``` cd demo python make_sample.py # generates sample.mcap (synthetic AV log, ~198 msgs) bash demo.sh # seal → verify INTACT → tamper → verify TAMPERED → inspect ``` 使用 [VHS](https://github.com/charmbracelet/vhs) 录制 `demo.gif`(需要 Docker): ``` docker build -f Dockerfile.vhs -t veriseal-vhs . docker run --rm -v "$(pwd):/vhs" veriseal-vhs demo/demo.tape ``` ## 路线图 - **v0.1:** 对 MCAP 进行封装 / 验证 / 检查 + OpenTimestamps 锚点 - **v0.2:** 监管链日志;RFC 3161 + Sigstore/Rekor 选项;ROS 2 bag 导入;HTML 报告 - **v0.3:** Web 查看器;封装守护进程;可插拔的透明度日志后端 ## 许可证 Apache-2.0 © Kyle Mapue
标签:CVE, Python, Zenmap, 区块链时间戳, 数字签名, 数据完整性, 无后门, 机器人日志, 逆向工具, 防篡改