keshavashiya/signet

GitHub: keshavashiya/signet

面向离网 mesh 网络的后量子消息认证协议,通过 TESLA 哈希链与 PQ 签名的双层设计,在带宽受限的无线电链路上实现低开销的消息真实性验证。

Stars: 0 | Forks: 0

# Signet 🕯 [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/keshavashiya/signet/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Status: alpha](https://img.shields.io/badge/status-alpha-orange.svg)](#status) **在灾难中,你无法分辨疏散命令是否真实。** Signet 是用于离网 mesh 网络的后量子真实性层。它依托 你的无线电现有的任何 payload 运行 —— Meshtastic、Bluetooth mesh、Reticulum、纯 LoRa —— 并回答现有协议栈 无法回答的一个问题:*这条消息真的来自其声称的发送者吗?* 印章戒指(Signet ring)是压入蜡中的封印:这是最古老的认证技术, 完全不需要任何基础设施,并能证明发送者 **而不 隐藏信件内容**。这正是该协议的设计理念 —— 真实性 优先,机密性可选。这也是为什么 Signet 在业余 频段是合法的,因为在这些频段禁止加密,但允许签名。 *无需服务器。无需账户。无需互联网。无需区块链。* 👉 **[完整文档](https://keshavashiya.github.io/signet)** — 协议 规范、架构、集成指南。 ## 快速开始 ``` git clone https://github.com/keshavashiya/signet.git cd signet cargo test --workspace # 101 tests, no network, no hardware, no C toolchain # 在 200 字节的有损链路上,真实性需要付出多少代价? cargo run --bin signet -- sim # 通过有损信道使用真实 FN-DSA 密钥的两个节点 cargo run --bin signet -- demo --loss 30 ``` ``` Signet airtime model — SF11 BW250kHz, MTU 237B, payload 30B, loss 20%, redundancy 30% scheme pq trailer frames air ms deliver eff ms note ---------------------------------------------------------------------------------------------------- Ed25519 NO 64 1 1026 80.0% 1283 1x what every mesh ships today TESLA (SHA-256) yes 48 1 903 80.0% 1129 1x 16B MAC + 32B disclosed key SQIsign-I yes 204 3/2 5904 89.6% 6590 6x NIST round 3; slow to sign MAYO-1 yes 392 3/2 5904 89.6% 6590 6x NIST round 3 HAWK-512 yes 555 4/3 7873 81.9% 9610 9x NIST round 3 FN-DSA-512 yes 666 6/4 11809 90.1% 13105 12x FIPS 206 draft ML-DSA-44 yes 2420 15/11 29522 83.6% 35323 31x FIPS 204, the safe default SLH-DSA-128s yes 7856 45/34 88566 82.6% 107238 95x FIPS 205, hash-based root ``` 再读一遍下半部分。**以显而易见的方式让离网 mesh 具备后量子特性,每条消息将花费 31 倍的信道占用时间。** 这就是为什么没人这么做,也是这个项目存在的原因。 ## 问题所在 | 系统 | 当前加密方式 | 后量子? | |---|---|---| | [Bitchat](https://github.com/permissionlesstech/bitchat) | Curve25519 (Noise XX) | ❌ | | [Meshtastic](https://meshtastic.org) | Curve25519 + AES-256-CTR | ❌ | | [Reticulum](https://reticulum.network) | X25519 / Ed25519 / AES-256 | ❌ | | [Briar](https://briarproject.org) | Ed25519 / X25519 | ❌ | Meshtastic 自己的文档明确指出:抗量子的密钥交换 *“不符合 LoRa 数据包的限制。”* 现有系统在自己的文档中承认了这一差距。 无线电流量极容易被拦截 —— 这是教科书式的 “现在截获,以后解密”(harvest-now-decrypt-later)目标。但更尖锐的问题不是机密性: - **加密已经幸存。** AES-256 在 Grover 算法面前只损失了一半的安全余量。 - **密钥交换是一次性的、可缓存的成本。** 虽然难看,但平摊下来几乎为零。 - **每条消息的真实性才会崩溃。** 而在灾难中,真实性 比保密性*更*重要 —— 错误信息会致命,而“这座桥断了” 必须能被证明是来自县 EOC 的。 ## 工作原理 两类消息,如何在它们之间做出选择是本项目的全部贡献。 ### A 类 — TESLA 哈希链(常规流量,16–48 字节) 发送者承诺一条单向哈希链的末端,使用只有自己持有的密钥对每个时间间隔的流量进行 MAC 处理,并在该间隔 结束后披露该密钥。在密钥公开*之前*收到消息的接收者知道, 其他任何人都无法伪造它。 ``` [16B MAC] typical [16B MAC] [32B disclosed key] first frame of each interval ``` **比 ML-DSA-44 签名小 50 倍**,构造上就是后量子安全的(它 仅仅是 SHA-256),并且原生支持容忍丢包 —— 错过三次披露, 第四次可以通过向前哈希恢复所有内容。披露是按间隔进行的, 因此突发发送多条消息的发送者只需一次支付 32 字节。 参见 [`chain.rs`](crates/core/src/chain.rs) 和 [`session.rs`](crates/core/src/session.rs)。 ### B 类 — 后量子签名(权威流量,666 字节) TESLA 提供经过身份验证的广播,**而不是**不可否认性:一旦密钥被 披露,任何人都可以追溯性地伪造该间隔的消息。因此,设计根据后果进行了分层。 | 消息 | 类别 | 成本 | |---|---|---| | 状态信标、聊天、传感器读数 | TESLA | 16–48 B | | 疏散命令、官方警报、凭证 | PQ 签名 | 666 B | 权威消息很少见。如果是一条要促使人们转移的消息,发送六个数据帧是完全可承受的。 ### 困难之处:时间 TESLA 需要发送者时钟的一个宽松上限,而在离网环境中是没有 NTP 的。Signet 会机会性地收紧本地单调时钟 —— 在有条件时使用 GPS,在节点联系时使用区间算术,将公共随机信标作为 单调下限 —— 然后**扩大披露延迟以弥补剩余的 不确定性,当不确定性超过阈值时回退到 B 类。** 安全条件和不确定性算术已经实现 ([`time.rs`](crates/core/src/time.rs));而良好边界的*来源*则是 Clock 阶段的工作。 系统会降级而不是直接失败 —— 运行 `signet demo --uncertainty-ms 600000` 即可看到每一帧是如何被正确拒绝的。参见 [`docs/protocol/time.md`](docs/src/protocol/time.md)。 ## 目录 - [状态](#status) - [使用该库](#using-the-library) - [集成](#integration) - [模拟器](#the-simulator) - [硬性规则](#hard-rules) - [路线图](#roadmap) - [开发](#development) - [安全性](#security) - [架构](#architecture) ## 状态 **Alpha —— 信道占用时间与协议部分已完成。** 该协议已完全规范并 实现了端到端:真正的 FN-DSA-512 证书、TESLA 链、 安全条件、纠删码分片以及经验证的事实存储。 101 项测试,尚未接入无线电。 | 阶段 | 产出内容 | 状态 | 产物 | |---|---|---|---| | **Airtime** | 在有损链路上真实性的成本是多少 | ✅ 完成 | `signet sim` | | **Protocol** | 链、证书、时钟、分片、会话 | ✅ 完成 | `signet demo`, 101 项测试 | | **Radio** | 基于 LoRa 硬件的 Meshtastic | ⬜ 下一步 | 两台 T-Beam | | **App** | 人们可以直接手持的设备 | ⬜ | 五个按钮,离线地图 | | **Clock** | 无需基础设施的时间同步 | ⬜ | 研究贡献 | | **Bluetooth** | 手机互联,无需额外硬件 | ⬜ | BLE 传输 | Protocol 阶段**没有**包含的功能:`Signed` 类发送路径(原语 已经有了,但还未进行组帧)、ML-KEM 机密性,以及任何传输层实现。 ## 使用该库 `signet-core` 是 `no_std` + `alloc` 的,因此同一套代码既可以在手机上运行,也可以在 Meshtastic 固件内的 ESP32 上运行。 ``` use signet_core::{chain::{self, Chain}, Schedule}; // Sender: commit once, publish the commitment in your operational cert. let chain = Chain::from_seed(&seed, 4096); let commitment = chain.commitment(); // Each interval: MAC the payload, disclose the key from `disclosure_delay` ago. let schedule = Schedule::default_at(epoch_ms); let interval = schedule.interval_at(now_ms); let tag = chain::mac(&chain.mac_key(interval)?, payload); let disclosed_interval = interval - schedule.disclosure_delay; let disclosed = chain.key(disclosed_interval)?; // Receiver: verify the disclosure advances the chain, then check the MAC. if chain::verify_disclosure(&anchor, anchor_interval, disclosed_interval, &disclosed) { let ok = chain::verify_mac(&chain::derive_mac_key(&disclosed), buffered, &tag); } ``` 存储模块在没有服务器、没有 CRDT 库的情况下合并已验证的事实: ``` use signet_core::Store; let mut store = Store::new(); store.merge(alice, STATUS, 5, b"need water"); store.merge(alice, STATUS, 3, b"ok"); // false — older, ignored // Independent claims are never collapsed into one "truth". let reports = store.by_kind(BRIDGE_OUT).count(); // "3 people report…" ``` ## 集成 **最终用户无法在已编译的应用中添加加密层。** Bitchat 没有 插件 API。实际可行的方案,按现实可行性排序如下: | 你的身份 | 你要做的事 | |---|---| | **Meshtastic 拥有者** | 安装 Signet 应用。通过手机 API 使用私有 portnum —— **无需更改固件,无需 fork**。 | | **任何应用,任何操作系统** | 分享菜单(Share-sheet)伴侣应用。在 Signet 中编写 → 分享 → 发送到 Bitchat。原生操作系统原语,不需要任何配合。 | | **Bitchat 用户,Android** | 使用分享菜单,或者侧载一个支持 Signet 的 fork 版本。 | | **Bitchat 用户,iOS** | 使用分享菜单,或者等待上游更新。其他方法都不切实际。 | | **维护者** | 三行代码。 | 对于维护者来说,集成被刻意设计得非常简单 —— UniFFI 从同一个 Rust 核心生成了 Swift 和 Kotlin 绑定: ``` let payload = signet.sign(text) // send path if let v = signet.verify(payload) { // receive path badge = v.trustLevel // .eoc / .known / .unverified } ``` 把它变成协议协商,没人会采用。把它变成一个返回徽章的函数调用,才有机会普及。 Signet 的设计还能在将其作为普通文本通过对其一无所知的传输层传输时安然无恙: ``` Evacuate north of 5th St --signet:1 from=GzJbRFwL2FM auth=n0wqfhHThbBsk_ohSOfQWw ``` 普通客户端会显示文本加上页脚的一行;Signet 客户端会验证、 隐藏页脚,并显示 ✅ **EOC 已验证**。该标记是纯 ASCII 字符,并 说明了其含义,因此从未听说过 Signet 的人可以搜索这个词 并了解它,而不是看到一堆乱码。 TESLA 的 16 字节 MAC 编码为 22 个 base64url 字符,因此典型的页脚 约为 55 个字符 —— 在聊天气泡中是可以忍受的。666 字节的签名约为 900 个字符,并不适宜,这也是支持双层设计的 另一个理由。格式在[集成指南](docs/src/guide/integration.md#footer-format)中有所规定。 ## 模拟器 ``` signet sim # single point signet sim --loss 0.4 --payload 100 # harsher link, bigger message signet sim --sweep --csv sim-out/air.csv # 0-50% loss, machine-readable signet sim --sf 7 --bw 125 # a different LoRa preset ``` 该模型是解析法,而不是蒙特卡洛模拟 —— 闭式二项式是精确的,并且 少了一个依赖项。有两个诚实的注意事项: - 丢包被建模为独立的。真实的 mesh 网络会丢失突发数据,这使得 多帧消息比显示的情况*更糟* —— 这里的每个数字都让 大型签名方案显得更好看。 - 多帧对象是经过纠删码处理的,而不是重传。在没有 反向通道的广播介质上,这胜过 ARQ,这也是为什么已发表的 需要 28–62 帧的 ML-KEM-over-LoRa 握手比必要的更糟的原因。 ## 硬性规则 保持范围诚实且代码可部署的十项不可妥协的原则。完整 文本和理由请见 [CONTRIBUTING.md](CONTRIBUTING.md#hard-rules): 1. `signet-core` 保持 `no_std` —— 它必须在 ESP32 上运行。 2. `signet-core` 保持仅使用哈希 —— `core` 中不得有后量子原语。 3. 永远不要实现自己的加密原语。 4. 无需 C 工具链 —— `cargo test` 在零系统依赖下即可运行。 5. 解析器对不受信任的输入永远不能引发 panic。 6. 每个拒绝路径都必须经过测试。 7. 通信协议的更改必须在同一个 PR 中更新 `PROTOCOL.md`。 8. 新的 crate 必须面临一个已经令人痛苦的边界。 9. 阶段以它们所交付的内容命名。 10. 拒绝清单:没有区块链或 token,没有撤销 PKI,没有 CRDT 库,没有新的 mesh 路由,没有服务器或账户,没有语音或视频。 ## 路线图 参见 [`docs/src/roadmap`](docs/src/roadmap/README.md)。简短版本:**Airtime、 Protocol 和 Radio 构成了这个项目。** 之后的所有内容都以硬件 数据保持良好为前提。 ## 开发 ``` just # list tasks just ci # fmt + clippy + no_std check + tests — run before pushing just sim # the airtime cost model just demo # two nodes over a lossy channel just docsserve # mdbook with live reload ``` 工作区布局: ``` crates/ core/ signet-core — wire format, chains, certs, time, frag, store (no_std) crypto/ signet-crypto — FN-DSA-512 signatures and cert operations cli/ signet — CLI: `sim` and `demo` docs/ mdbook source PROTOCOL.md the wire protocol ``` 三个 crate。`core` 保持 `no_std` 且仅使用哈希,以便它能在 ESP32 上的 Meshtastic 固件中运行;`crypto` 包含所有需要比 哈希函数更多功能的组件。参见 [CONTRIBUTING.md](CONTRIBUTING.md)。 ## 安全性 Signet 处于 **alpha 阶段且未经审计**。不要在出错会有严重后果的 场景下依赖它。设计在 [PROTOCOL.md](PROTOCOL.md) 中有详细记录,正是为了让任何人能在实际部署之前 从理论上对其进行攻击。 已知的差距在 [`docs/src/protocol/threat-model.md`](docs/src/protocol/threat-model.md) 中公开跟踪 —— 包括公共随机信标自身的签名不是 后量子安全的这个问题。 要报告漏洞,请不要公开 issue —— 使用 Security 标签页下 GitHub 的私人 报告功能。参见 [SECURITY.md](SECURITY.md)。 ## 架构 关于分层模型、crate 边界 以及每个设计决策背后的原因,请参见 [ARCHITECTURE.md](ARCHITECTURE.md)。 ## 许可证 MIT —— 详见 [LICENSE](LICENSE)。
标签:CVE, LoRa物联网, Rust, 可视化界面, 后量子密码学, 数字签名, 离网自组网, 网络流量审计, 通知系统