obsTR/quantum-notary
GitHub: obsTR/quantum-notary
一个基于 Dilithium5 后量子签名的命令行工具,为软件物料清单(SBOM)提供抗量子计算的安全签名与验证能力。
Stars: 173 | Forks: 8
# qs_notary – 后量子 SBOM 公证 CLI
**qs_notary** 是一个用于使用**后量子密码学**(Dilithium5)对软件物料清单(SBOM)进行加密**签名**和**验证**的命令行工具。它借助 NIST 标准的量子抗性签名、透明日志记录以及可选的基于策略的验证,帮助保护软件供应链安全。
[](https://doi.org/10.5281/zenodo.18588477)
## 目录
- [功能特性](#features)
- [系统要求](#requirements)
- [安装说明](#installation)
- [快速入门](#quick-start)
- [命令参考](#commands-reference)
- [generate-keys](#generate-keys)
- [sign](#sign)
- [verify](#verify)
- [sign-all](#sign-all)
- [透明日志服务器(qs_server)](#transparency-log-server-qs_server)
- [策略引擎](#policy-engine)
- [签名格式](#signature-format)
- [许可证](#license)
## 功能特性
- **后量子签名** – 使用 **Dilithium5**(NIST PQC 标准)进行签名,确保未来量子计算机也无法破解。
- **SBOM 支持** – 验证并签名 **CycloneDX** 和 **SPDX** 格式的 JSON SBOM;拒绝签名无效或未知格式。
- **内容绑定** – 对文件的 **SHA3-256** 哈希值签名,任何改动都会使签名失效。
- **密钥管理** – 默认使用本地密钥文件;提供可选的 **mock KMS** 模式(`--kms`)用于测试远程签名。
- **透明日志** – 本地追加式账本(例如 `ledger.json`),并支持可选的**远程日志服务器**(`--server-url`)实现集中审计。
- **基于策略的验证** – 可选**策略文件**(`--policy`)强制执行密钥白名单和**最大签名有效期**。
- **批量签名** – **sign-all** 递归地对目录中的每个文件签名,并生成一个签名**清单**作为信任根。
## 系统要求
- **Rust** 1.70+(从 [rustup.rs](https://rustup.rs) 安装)
- **Windows**:安装“桌面开发 with C++”的 Visual Studio 生成工具(MSVC)或 MinGW 工具链
## 安装说明
克隆仓库并编译构建:
```
git clone https://github.com/your-org/quantum-notary.git
cd quantum-notary
cargo build --release
```
**二进制文件位置:**
| 二进制文件 | Windows | Linux / macOS |
|--------------|------------------------------|----------------------------|
| **qs_notary** | `target\release\qs_notary.exe` | `target/release/qs_notary` |
| **qs_server** | `target\release\qs_server.exe` | `target/release/qs_server` |
**运行方式:** 使用**项目根目录**(`quantum-notary`)中的二进制文件,而不是 `target\release` 内部。命令中的密钥、账本文件和路径均相对于**当前工作目录**。
从项目根目录执行:
- **Windows(PowerShell):**
`.\target\release\qs_notary.exe ...`
- **Linux / macOS:**
`./target/release/qs_notary ...`
可选:将 `target/release`(Windows 上为 `target\release`)添加到 `PATH`,或将可执行文件复制到已在 `PATH` 中的文件夹,以便在任何位置运行 `qs_notary` 和 `qs_server`。
## 快速入门
从**项目根目录**运行,以便在当前目录创建 `public.key` 和 `private.key`(或使用 `--output-dir` 指定其他目录)。
**Windows(PowerShell):**
```
# 在当前目录生成密钥对(写入 public.key 和 private.key)
.\target\release\qs_notary.exe generate-keys
# 签署 SBOM(例如 CycloneDX 或 SPDX JSON)
.\target\release\qs_notary.exe sign sbom.json --private-key private.key
# 验证已签署的 SBOM
.\target\release\qs_notary.exe verify sbom.json sbom.json.sig --public-key public.key
```
**Linux / macOS:**
```
./target/release/qs_notary generate-keys
./target/release/qs_notary sign sbom.json --private-key private.key
./target/release/qs_notary verify sbom.json sbom.json.sig --public-key public.key
```
验证成功时打印 **Verified Safe**(绿色);失败时打印 **Verification Failed**(红色)。
## 命令参考
### generate-keys
生成 Dilithium5 密钥对,并将 `public.key` 和 `private.key` 写入磁盘。文件默认写入**当前工作目录**;可通过 `--output-dir` 指定其他目录。请从项目根目录运行(或使用 `--output-dir`),以免密钥被创建在 `target\release` 内部。
| 参数 / 标志 | 说明 |
|--------------------|------|
| `--output-dir ` | 密钥文件输出目录(默认:当前目录) |
**示例:**
```
# 从项目根目录(密钥存入项目根目录)
.\target\release\qs_notary.exe generate-keys
.\target\release\qs_notary.exe generate-keys --output-dir .\keys
```
如果已在 `target\release` 运行并生成了密钥,可将其移至项目根目录:
`Move-Item .\target\release\public.key .` 和 `Move-Item .\target\release\private.key .`
### sign
签名单个 SBOM 文件。验证文件是否为有效 JSON 并包含 CycloneDX(`bomFormat`)或 SPDX(`spdxVersion`)标记后才进行签名。签名文件生成 `.sig` 文件,写入本地账 ledger(并可选择上传到服务器)。
| 参数 / 标志 | 必填 | 说明 |
|------------------------|------|------|
| `SBOM` | 是 | SBOM 文件路径(例如 `sbom.json`) |
| `-k, --private-key ` | 是* | 私钥文件路径(若设置 `--kms` 则忽略) |
| `--kms` | 否 | 使用模拟 KMS(内存密钥,100ms 延迟)用于测试 |
| `--ledger ` | 否 | 账本文件路径(默认:`ledger.json`) |
| `--server-url ` | 否 | 透明日志服务器 URL(例如 `http://localhost:8080`);后台异步上传条目;若服务器不可达仍可完成签名 |
**示例:**
```
qs_notary sign sbom.json --private-key private.key
qs_notary sign sbom.json -k private.key --server-url http://localhost:8080
qs_notary sign sbom.json --private-key private.key --ledger my_ledger.jsonl
qs_notary sign sbom.json --kms # mock KMS (test only; use matching public key for verify)
```
**输出:** 创建 `sbom.json.sig`(或其他扩展名对应的 `..sig`),并在账本中追加一条记录。
### verify
验证 SBOM 文件及其签名。重新计算文件哈希并检查 Dilithium5 签名。可选应用策略(密钥白名单、最大有效期)。
| 参数 / 标志 | 必填 | 说明 |
|------------------------|------|------|
| `SBOM` | 是 | 原始 SBOM 文件路径 |
| `SIGNATURE` | 是 | 签名文件路径(例如 `sbom.json.sig`) |
| `-k, --public-key ` | 是 | 公钥文件路径 |
| `--policy ` | 否 | 策略 JSON 文件;启用时强制执行白名单和/或最大有效期 |
**示例:**
```
qs_notary verify sbom.json sbom.json.sig --public-key public.key
qs_notary verify sbom.json sbom.json.sig -k public.key --policy policy.json
```
**退出/输出:** 验证成功打印 **Verified Safe**(绿色);若签名无效或策略检查失败,打印 **Verification Failed**(红色)并以错误码退出。
### sign-all
递归签名目录中的所有文件,随后在目录根目录创建并签名一个**清单**。跳过隐藏文件(名称以 `.` 开头)和已有 `.sig` 文件。不验证 SBOM 格式(可签名任意文件)。
| 参数 / 标志 | 必填 | 说明 |
|------------------------|------|------|
| `DIR` | 是 | 要递归遍历的目录 |
| `-k, --private-key ` | 是* | 私钥文件路径(若设置 `--kms` 则忽略) |
| `--kms` | 否 | 使用模拟 KMS(测试专用) |
| `--ledger ` | 否 | 账本文件(默认:`ledger.json`) |
| `--server-url ` | 否 | 透明日志服务器;每个签名文件触发一次后台上传 |
**示例:**
```
qs_notary sign-all ./dist --private-key private.key
qs_notary sign-all ./artifacts -k private.key --server-url http://localhost:8080
```
**输出:**
- 对每个文件:创建 `..sig`(带时间戳的封装格式)。
- 在 `DIR` 中写入 **manifest.json**,包含 `entries: [{ "path": "relative/path", "_hash": "hex" }, ...]`。
- 签名 **manifest.json** 并生成 **manifest.json.sig**(作为该目录的信任根)。
## 透明日志服务器(qs_server)
**qs_server** 是独立的可执行文件,用于运行 HTTP 服务器以提供共享透明日志。CLI 可在签名后通过 `--server-url` 将其账本条目发送至该服务器。
**运行服务器:**
```
qs_server
```
- 监听 **0.0.0.0:8080**。
- **POST /upload** – 请求体为 JSON `{ "file_name", "signature_hash", "timestamp" }`。将一行 JSON 追加到**服务器当前目录下的 central_ledger.jsonl**。
- 成功返回 **200**,无效 JSON 返回 **400**,写入错误返回 **500**。
**CLI 示例:**
```
# 终端 1
qs_server
# 终端 2
qs_notary sign sbom.json --private-key private.key --server-url http://localhost:8080
```
若服务器不可达,签名命令会记录警告,但仍会完成(本地账本和 `.sig` 文件仍会被写入)。
## 策略引擎
使用 **--policy <FILE>** 与 **verify** 配合以强制执行:
- **allowed_public_keys** – 仅接受列出的公钥(十六进制编码)。
- **max_age_days** – 超过指定天数的签名将被拒绝(签名中需包含时间戳;参见[签名格式](#signature-format))。
- **allow_expired** – 若为 `true`,则不强制执行 `max_age_days`。
**policy.json 示例:**
```
{
"allow_expired": false,
"max_age_days": 90,
"allowed_public_keys": [
"a1b2c3d4e5f6...hex-encoded-public-key-bytes..."
]
}
```
- 省略字段或设为 `null` 表示“无限制”。
- 一次性获取公钥的十六进制值(例如 `hex::encode(public_key.as_bytes())` 或通过工具获取),并将其加入 `allowed_public_keys`。
**策略失败消息:**
- `Verification failed: public key not in policy allowlist.`
- `Verification failed: signature has no timestamp; cannot apply max_age_days.`
- `Verification failed: signature older than max_age_days.`
## 签名格式
- **新签名**以**封装格式**存储:`.sig` 文件为 JSON
`{ "signature": "", "timestamp": "" }`。
- 仍支持原始的**二进制** `.sig` 文件(遗留格式);验证时将其视为无时间戳(若策略要求 `max_age_days` 则会失败)。
## 项目结构(开发者参考)
| 路径 | 用途 |
|----------------------|------|
| `src/main.rs` | CLI 入口点及子命令 |
| `src/crypto.rs` | Dilithium5 密钥对、签名/验证、密钥与签名加载/保存 |
| `src/key_provider.rs`| KeyProvider 特性、FileSystemProvider、MockKmsProvider |
| `src/sign.rs` | sign 命令:SBOM 验证、哈希、签名、账本、可选服务器上传 |
| `src/verify.rs` | verify 命令:加载签名(封装或原始)、加密验证、策略检查 |
| `src/sign_all.rs` | sign-all:递归遍历、逐个签名文件、生成清单并签名清单 |
| `src/ledger.rs` | 追加式本地账本(JSON Lines) |
| `src/policy.rs` | 策略加载与字段定义 |
| `src/bin/qs_server.rs` | HTTP 服务器,处理 POST /upload → 写入 central_ledger.jsonl |
## 许可证
请参阅仓库中的 LICENSE 文件。本项目在供应链安全工作流中使用后量子密码学(Dilithium5)进行 SBOM 签名与验证。
标签:CLI, CycloneDX, Dilithium5, Homebrew安装, NIST PQC, Rust, SBOM, SHA3-256, SPDX, WiFi技术, 供应链完整性, 内容绑定, 区块链式账本, 可视化界面, 后量子密码, 审计追踪, 批量签名, 政策引擎, 文档结构分析, 硬件无关, 策略验证, 签名验证, 网络流量审计, 软件供应链安全, 软件完整性, 远程方法调用, 透明日志, 量子安全, 防篡改