muc111/OTRv4Plus

GitHub: muc111/OTRv4Plus

实现 OTRv4 协议的后量子 IRC 客户端,结合 ML-KEM-1024 密钥交换和 ML-DSA-87 认证,通过 Rust 棘轮核心确保内存安全清零,支持 I2P/Tor 网络匿名通讯。

Stars: 3 | Forks: 0

![OTR v4+ 后量子密码学标志](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/3b41c22497131336.png) # Off The Record v4 Plus PQC (OTRv4) 基于 IRC 的后量子加密通讯。为 I2P 构建,兼容所有网络。 这是唯一实现后量子密码学的 OTRv4 客户端。密钥交换、认证和棘轮都使用 NIST 标准化的后量子密码学以及经典密码学。即使量子计算机攻破 X448,您的消息——无论是过去的还是未来的——都将受到保护。 客户端默认通过 I2P 的 SOCKS5 代理连接到 `irc.postman.i2p`。指向任何 IRC 服务器,它会自动检测网络:`.i2p` 通过 I2P 路由,`.onion` 通过 Tor 路由,其他所有都使用 TLS 直连。无需手动配置代理。 一个 Python 文件(约 12,000 行),三个 C 扩展,一个 Rust 棘轮核心,224 个测试。在手机上运行 Termux 即可使用。 ## I2P 快速入门 如果您已经在运行 I2P,可以开箱即用: ``` git clone https://github.com/muc111/OTRv4Plus.git cd OTRv4Plus # On Debian/Ubuntu/Arch/macOS — 首先创建虚拟环境: python3 -m venv ~/otr-env && source ~/otr-env/bin/activate pip install cryptography pysocks # On Termux — pip 可以直接使用: # pip install cryptography pysocks # 构建 C 扩展(所有平台) python setup_otr4.py build_ext --inplace bash build_ed448.sh gcc -shared -fPIC -O2 -o otr4_mldsa_ext.so otr4_mldsa_ext.c \ $(python3-config --includes) $(python3-config --ldflags --embed) -lcrypto # 运行 — 默认连接到 irc.postman.i2p PYTHONMALLOC=malloc python otrv4+.py ``` 客户端通过 I2P 的 SOCKS5 代理(`127.0.0.1:4447`)连接到 `irc.postman.i2p:6667`。进入后,`/join #otr` 或任何频道,然后 `/otr ` 与某人开始加密会话。 对于直连网络或 Tor: ``` # Libera.Chat with TLS PYTHONMALLOC=malloc python otrv4+.py -s irc.libera.chat:6697 # Tor 隐藏服务 PYTHONMALLOC=malloc python otrv4+.py -s palladium.libera.chat.onion:6667 # SASL 登录 PYTHONMALLOC=malloc python otrv4+.py -s irc.libera.chat --sasl -n YourNick # 指定端口,无 TLS PYTHONMALLOC=malloc python otrv4+.py -s irc.example.com -p 6667 --no-tls ``` `PYTHONMALLOC=malloc` 让 C 扩展使用 `mlock()` 来保护内存页。您可以省略它进行快速测试,但实际使用中应该启用。 ⚠️ 棘轮后端:强烈推荐使用 Rust 此客户端有两个棘轮后端: · 🦀 Rust(推荐)——所有链密钥、根密钥、支撑密钥、消息密钥和跳过密钥都存储在 Rust 结构中,这些结构实现了带有 Zeroize 特性的 Drop。当棘轮被销毁时,密钥会被确定性地覆盖——独立于 Python 的垃圾回收器。 · 🐍 Python + C 扩展(后备)——仅在无法在您的平台上构建 Rust 时使用(例如某些较旧的 Termux 环境)。密钥通过 `__del__` 中的 `OPENSSL_cleanse` 清除,但 Python 的 GC 可能会延迟最终化。这不如 Rust 后端安全。 尽可能始终安装 Rust 棘轮核心。启动横幅会显示 🦀 Rust (zeroize-on-drop) 表示已激活。如果看到 🐍 Python (C extensions),则您正在运行后备版本。 ## 平台设置 每个平台都需要:Python 3.9+、OpenSSL 3.5+、C 编译器以及 `cryptography` 和 `pysocks` pip 包。在 Debian/Ubuntu 23.04+、Arch 和 macOS 上,pip 需要虚拟环境——下面的平台部分包含 venv 设置。Termux 没有此限制。Rust 棘轮核心是可选的但推荐使用——没有它,链密钥会通过 Python 的垃圾回收器清除,而不是被确定性清零。 ### Termux(Android) Termux 不强制执行外部管理环境限制,因此可以直接使用 `pip install`。 ``` # 核心依赖 pkg install python openssl clang build-essential git # Python 包 pip install cryptography pysocks # I2P — 从 Termux 仓库安装 i2pd 或使用 Java I2P Android 应用 # i2pd 默认在 127.0.0.1:4447 暴露 SOCKS5 pkg install i2pd # 在后台启动 i2pd: i2pd --daemon # Tor(可选) pkg install tor tor & # SOCKS5 on 127.0.0.1:9050 # Rust ratchet 核心(可选,推荐) pkg install rust pip install maturin cd Rust cargo test --release export ANDROID_API_LEVEL=24 maturin build --release pip install target/wheels/otrv4_core-*.whl --break-system-packages cd .. ``` ### Debian / Ubuntu Ubuntu 23.04+ 和 Debian 12+ 阻止系统级 `pip install`。请使用虚拟环境。 ``` # 核心依赖 sudo apt update sudo apt install python3 python3-dev python3-pip python3-venv \ libssl-dev build-essential git # 创建并激活虚拟环境 python3 -m venv ~/otr-env source ~/otr-env/bin/activate # Python 包(在虚拟环境内 — 无需 --break-system-packages) pip install cryptography pysocks # I2P — 来自官方仓库的 i2pd sudo apt install apt-transport-https wget -q -O - https://repo.i2pd.xyz/.help/add_repo | sudo bash -s - sudo apt update sudo apt install i2pd # i2pd 自动启动;SOCKS5 在 127.0.0.1:4447 # Tor(可选) sudo apt install tor # 自动启动;SOCKS5 在 127.0.0.1:9050 # Rust ratchet 核心(可选,推荐) curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env pip install maturin cd Rust cargo test --release maturin build --release pip install target/wheels/otrv4_core-*.whl cd .. # 重要提示:运行客户端前务必激活虚拟环境 # source ~/otr-env/bin/activate ``` ### Arch Linux Arch 在最新版本上也强制执行外部管理环境。 ``` # 核心依赖 sudo pacman -S python python-pip openssl base-devel git # 创建并激活虚拟环境 python3 -m venv ~/otr-env source ~/otr-env/bin/activate # Python 包 pip install cryptography pysocks # I2P sudo pacman -S i2pd sudo systemctl enable --now i2pd # Tor(可选) sudo pacman -S tor sudo systemctl enable --now tor # Rust ratchet 核心(可选,推荐) sudo pacman -S rust pip install maturin cd Rust && cargo test --release && maturin build --release pip install target/wheels/otrv4_core-*.whl cd .. ``` ### macOS(Homebrew) ``` # 核心依赖 brew install python openssl@3 git # 创建并激活虚拟环境 python3 -m venv ~/otr-env source ~/otr-env/bin/activate # Python 包 — 指向 Homebrew 的 OpenSSL LDFLAGS="-L$(brew --prefix openssl@3)/lib" \ CFLAGS="-I$(brew --prefix openssl@3)/include" \ pip install cryptography pysocks # I2P — 通过 Homebrew 安装 i2pd brew install i2pd brew services start i2pd # Tor(可选) brew install tor brew services start tor # Rust ratchet 核心(可选,推荐) brew install rust pip install maturin cd Rust && cargo test --release && maturin build --release pip install target/wheels/otrv4_core-*.whl cd .. ``` ### 验证 OpenSSL ML-KEM-1024 和 ML-DSA-87 需要 OpenSSL 3.5+。如果您的发行版提供的是旧版本,C 扩展将无法构建。 ``` openssl version # 必须显示:OpenSSL 3.5.0 或更高版本 # 如果显示 3.x 低于 3.5,需要从源码构建 OpenSSL # 或使用反向移植。Termux 默认附带 3.5+。 ``` ## 工作原理 您启动客户端。它连接到 IRC(默认使用 I2P)。您加入一个频道,看到谁在里面,然后输入 `/otr SomeNick` 开始加密会话。 幕后流程: 1. **DAKE 握手**——三条消息(DAKE/DAKE2/DAKE3)使用三重 X448 Diffie-Hellman + ML-KEM-1024 后量子封装建立共享秘密。第三条消息携带 Ed448 环签名(可否认认证)和可选的 ML-DSA-87 签名(后量子认证)。 2. **双棘轮**——每条消息从链中派生出新的加密密钥。每 50 条消息(或 5 分钟),DH 棘轮步骤会生成新的临时密钥。每个 DH 棘轮还会轮换 ML-KEM 支撑密钥,因此后量子保护在泄密后会自愈。 3. **SMP 验证**——双方输入相同的共享秘密(`/smp mysecret`),然后 `/smp start`。社会主义百万富翁协议证明他们知道相同的秘密而不会泄露。使用 3072 位 DH 和零知识证明。口令通过 10,000 轮 SHAKE-256 拉伸。 4. **关闭**——执行 `/quit` 时,每个棘轮都会被清零(Rust `Drop` 特性覆盖所有密钥字节),屏幕被清除,持久数据被安全擦除。 会话指示器显示安全级别:🔴 明文,🟡 加密(未验证),🟢 指纹可信,🔵 SMP 已验证。 ## 网络自动检测 客户端检查您提供的主机名: | 主机名模式 | 网络 | 代理 | 默认端口 | |---|---|---|---| | `*.i2p` | I2P | `127.0.0.1:4447`(SOCKS5) | 6667 | | `*.onion` | Tor | `127.0.0.1:9050`(SOCKS5) | 6667 | | 其他任何 | 直连 | 直接 | 6697(TLS) | 无需标志。`irc.postman.i2p` 通过 I2P 路由。`palladium.libera.chat.onion` 通过 Tor 路由。`irc.libera.chat` 直接连接,TLS 自动协商。 I2P 用户:请确保 i2pd(或 Java I2P)正在运行,并且 SOCKS5 代理在端口 4447 上启用。如果无法访问代理,客户端会提示您。 ## 架构 ``` ┌─────────────────────────────────────────────────────┐ │ otrv4+.py │ │ IRC client, UI, DAKE, SMP, config │ │ (~12,000 lines) │ ├─────────────┬─────────────┬─────────────────────────┤ │ Rust core │ C extensions│ Python cryptography │ │ otrv4_core │ 3 × .so │ (OpenSSL bindings) │ ├─────────────┼─────────────┼─────────────────────────┤ │ AES-256-GCM │ ML-KEM-1024 │ X448 key exchange │ │ SHAKE-256 │ Ed448 ring │ Ed448 signatures │ │ Chain KDF │ signatures │ ML-DSA-87 (via EVP) │ │ Skip keys │ BN ct arith │ │ │ Replay det │ Memory lock │ │ │ Zeroize │ OSSL cleanse│ │ └─────────────┴─────────────┴─────────────────────────┘ OpenSSL 3.5+ ``` Rust 核心处理双棘轮——这是消息密钥存活时间最长、最关键的地方。所有链密钥、根密钥、支撑密钥、消息密钥和跳过密钥在删除时都会被确定性清零。如果未安装 Rust,客户端会回退到等效的 Python 代码,由相同的 C/OpenSSL 加密支持。无论哪种方式,协议和有线格式都是相同的。 启动横幅会告诉您正在运行哪个后端: ``` OTRv4 IRC Client ================================================== Version : OTRv4+ 10.0 Server : irc.postman.i2p:6667 Network : 🧅 I2P (plaintext) Auth : anonymous Channel : #otr Debug : OFF Ratchet : 🦀 Rust (zeroize-on-drop) ================================================== ``` ## 密码学堆栈 **密钥交换(DAKE):** 三重 X448 Diffie-Hellman + ML-KEM-1024 封装(FIPS 203)。KEM 共享秘密混合到根密钥派生中。必须同时攻破经典和后量子密钥材料才能破解会话。 **认证(DAKE3):** Ed448 Schnorr 环签名用于经典可否认性 + ML-DSA-87(FIPS 204)用于后量子认证。环签名意味着任何一方都无法证明对方参与了签名。ML-DSA 意味着量子对手无法伪造您的身份。这些共存——对经典对手可否认,对量子对手可认证。 **棘轮:** OTRv4 双棘轮,每隔一个 DH 周期轮换 ML-KEM-1024 支撑密钥。支撑密钥从 DAKE 的 KEM 共享秘密开始,在每个 DH 棘轮时用新的 KEM 材料轮换。后量子保护在泄密后自愈。 **每条消息:** AES-256-GCM,带 12 字节随机随机数。密钥通过 SHAKE-256 派生(KDF_1,规格 §3.2)。MAC 密钥是 SHA3-512。通过 Grover 界限实现 128 位后量子对称安全。 **SMP:** RFC 3526 第 15 组(3072 位安全素数)。Fiat-Shamir 零知识证明。所有模幂运算通过 OpenSSL 的 `BN_mod_exp_mont_consttime`。口令通过 10,000 轮 SHAKE-256 拉伸,使用 `OTRv4+SMP\x00` 域分隔符。 不使用 liboqs。所有后量子密码学使用 OpenSSL 3.5+ 原生 FIPS 203/204 提供程序。 ## C 扩展 | 文件 | 行数 | 功能 | |---|---|---| | `otr4_crypto_ext.c` | 1866 | BN 常数时间运算、ML-KEM-1024(完整 NTT 实现)、Ed448 环签名、`mlock()`/`OPENSSL_cleanse` 内存加固 | | `otr4_ed448_ct.c` | 867 | 使用 Montgomery 梯和基于 XOR 的 `cswap` 进行常数时间 Ed448 标量乘法——不在秘密位上分支 | | `otr4_mldsa_ext.c` | 321 | 通过 OpenSSL 的 EVP API 实现 ML-DSA-87 密钥生成/签名/验证 | 这些是必需的。没有它们客户端拒绝启动。 ### 构建 ``` python setup_otr4.py build_ext --inplace bash build_ed448.sh gcc -shared -fPIC -O2 -o otr4_mldsa_ext.so otr4_mldsa_ext.c \ $(python3-config --includes) $(python3-config --ldflags --embed) -lcrypto ``` 如果任何扩展失败,请检查是否安装了 `python3-dev`(或 `python3-devel`)和 `libssl-dev`(或 `openssl-devel`),并且 `openssl version` 显示 3.5+。 ## Rust 棘轮核心 双棘轮通过 PyO3 在 Rust 中运行。当棘轮被删除时,每个秘密字节都会被零覆盖——由 Rust 的 `Zeroize` 特性保证,不依赖于 Python 的垃圾回收器。 ``` cd Rust cargo test --release # 11 tests in 0.01s maturin build --release pip install target/wheels/otrv4_core-*.whl --break-system-packages ``` 在 Termux 上,运行 `maturin build` 前设置 `export ANDROID_API_LEVEL=24`。 零个 `unsafe` 块。Rust 代码处理:SHAKE-256 KDF、AES-256-GCM 加密/解密、链密钥推进、跳过密钥存储(带有 `ZeroizeOnDrop` 条目的 `BTreeMap`)、重放检测和支撑密钥轮换。 X448/Ed448 密钥交换留在 Python 中(通过 `cryptography` 库的 OpenSSL)。ML-KEM 和 ML-DSA 留在 C 扩展中。Rust 和 Python 在相同的有线格式上互操作。 如果未安装 Rust 模块,客户端会静默回退到 Python 棘轮。两个后端都通过相同的 224 个测试。 ## 有线格式 ``` DAKE1: 0x35 ‖ X448_eph(56) ‖ MLKEM_ek(1568) ‖ profile(var) [‖ MLDSA_pub(2592)] DAKE2: 0x36 ‖ X448_eph(56) ‖ MLKEM_ct(1568) ‖ profile(var) [‖ MLDSA_pub(2592)] ‖ MAC(64) DAKE3: 0x37 ‖ ring_sigma(228) ‖ flag(1) [‖ MLDSA_sig(4627)] DATA: 0x00 ‖ 0x04 ‖ 0x03 ‖ header(64) ‖ nonce(12) ‖ ciphertext(var) ‖ tag(16) ``` ML-DSA 字段使用标志字节编码——`0x01` 表示存在,`0x00` 表示不存在。没有 ML-DSA 的对等方回退到仅使用经典环签名。完全向后兼容。 OTR 消息为 IRC 行限制进行分片(每个分片 300 字节),使用规格 §4.7 有线格式:`?OTRv4|sender_tag|receiver_tag|k|n|data.` ## 命令 **IRC:** `/join #channel` `/part` `/nick newnick` `/msg nick message` `/names` `/topic` `/list` `/whois nick` `/invite nick #channel` `/kick nick` `/mode` `/notice` `/away message` `/back` `/raw COMMAND` `/reconnect` `/quit` **OTR:** `/otr nick` 开始会话(发送 DAKE1)。`/endotr nick` 结束会话。`/fingerprint` 显示您的和对方的指纹。`/trust nick` 将指纹标记为可信。`/smp secret` 设置验证口令。`/smp start` 开始验证。`/smp abort` 取消。`/smp status` 显示进度。`/secure` 列出所有活动会话。 **UI:** `/switch panelname` `/tabs` `/tab-next` `/tab-prev` `/tab-close` `/clear` `/ignore nick` `/unignore nick` `/ignored` `/status` `/debug` `/version` ## 测试 ``` # 标准套件(Termux 上约 2 分钟) pytest -v test_*.py fuzz_harnesses.py -k "not 300k" # 完整测试流程,包括 30 万条消息的严苛测试(约 8 小时) pytest -v test_*.py fuzz_harnesses.py ``` 224 个测试分布在 10 个文件中:10k/50k/100k 消息的双棘轮正确性、状态分叉攻击、重放抵抗、前向保密擦除、泄密后恢复、乱序交付、ML-KEM 往返、ML-DSA 混合验证、环签名不可延展性、有线格式模糊测试、SMP 零知识证明、DAKE 状态机转换和差分属性测试。 ## 安全状态 | 层 | 运行位置 | 秘密清零 | |---|---|---| | 双棘轮(链/根/支撑/消息密钥) | Rust | 确定性——删除时 `Zeroize` | | AES-256-GCM 加密/解密 | Rust | 确定性 | | SHAKE-256 KDF | Rust | 确定性 | | 跳过密钥 + 重放缓存 | Rust | `BTreeMap` 条目上的 `ZeroizeOnDrop` | | ML-KEM-1024 | C 扩展 | `OPENSSL_cleanse` | | ML-DSA-87 | C 扩展(OpenSSL EVP) | `OPENSSL_cleanse` | | Ed448 环签名 | C 扩展(常数时间) | `OPENSSL_cleanse` | | Ed448 标量乘法 | C 扩展(Montgomery cswap) | `OPENSSL_cleanse` | | X448 密钥交换 | Python `cryptography`(OpenSSL) | OpenSSL 管理 | | SMP 指数(a2, b3, r5...) | Python(OpenSSL BN 运算) | GC 依赖(秒级) | | DAKE 临时密钥 | Python | GC 依赖(毫秒级) | 棘轮是秘密存活时间最长的地方——每条消息密钥、每次链推进、每次用于乱序交付的跳过密钥。现在这些都是 Rust,具有保证的清零。SMP 指数在握手期间存在几秒钟。DAKE 临时密钥是一次性的。 ## 与 Signal PQXDH 的比较 Signal 的 PQXDH(2024 年修订版 3)在初始握手中添加了 ML-KEM,但未升级认证。他们的规格明确指出:"PXDH 中的认证不是量子安全的"和"后量子安全可否认相互认证是一个开放的研究问题。" 此客户端采用不同的方法。ML-DSA-87 提供后量子认证,代价是后量子可否认性——量子对手可以验证签名并证明您参与了签名。环签名仍然提供经典可否认性。标准中不存在后量子可否认签名,因此这是最佳可用选项。 | | Signal PQXDH | OTRv4+ | |---|---|---| | 后量子密钥交换 | 仅在握手时使用 ML-KEM | DAKE 时使用 ML-KEM-1024 + 每个棘轮周期 | | 后量子认证 | 无 | ML-DSA-87 混合 | | 经典可否认性 | 是 | 是(环签名) | | 后量子可否认性 | 否 | 否(开放问题) | | 异步支持 | 是(预密钥服务器) | 否(双方在线,IRC) | | 棘轮内存安全 | GC 依赖 | Rust zeroize-on-drop | ## 已知限制 端点泄密胜过一切。root 手机、恶意 Termux 包或屏幕捕获恶意软件会绕过所有加密。这对于每个加密通讯应用都是如此,不仅仅是这一个。 I2P 流量分析可以通过分片数量识别 OTR 握手——DAKE 消息会产生 20-25 条 IRC 行的独特突发。无法在分片层添加填充,需要协议级更改(加密信封内的 PADDING TLV)。这是代码库中记录的已知限制。 昵称生成器从组合池中产生约 11,000 个唯一昵称。如果观察者看到您使用不同昵称重新连接,这会减少但不能消除跨会话关联。 SMP 安全性取决于口令熵。10,000 倍 SHAKE-256 拉伸使暴力破解更加困难,但短口令(少于 6 个字符)仍然容易受到攻击。客户端会警告您。 直连连接会在 IRC WHOIS 中暴露您的 IP,直到昵称隐藏激活。使用 I2P 或 Tor 来避免这种情况。 一个密码学缺口是后量子可否认性。不存在标准化的原语。当存在时,DAKE3 中的标志字节机制支持升级而不会破坏向后兼容性。 ## 数据 所有持久化数据都存储在 `~/.otrv4plus/` 中: - `trust.json`——指纹信任数据库(TOFU) - `smp_secrets.json`——SMP 秘密(静态时 XOR 混淆) - `keys/`——Ed448 身份密钥、X448 预密钥(加密) - `logs/otrv4plus.log`——轮转事件日志 执行 `/quit` 时,活动会话会被清零(Rust 确定性擦除用于棘轮密钥,`OPENSSL_cleanse` 用于 C 扩展秘密),屏幕被清除。 ## 许可证 GPL-3.0 用于开源使用——请参阅 [LICENSE](LICENSE)。 商业许可证可用于专有集成——请参阅 [COMMERCIAL-LICENSE.md](
标签:C扩展, I2P, IRC, KEM, ML-DSA, NIST标准, OTR, Python, Rust, Termux, Tor, X448, 加密通讯, 匿名通讯, 即时通讯, 可视化界面, 后量子密码学, 抗量子计算, 无后门, 混合密码学, 端到端加密, 网络安全, 网络安全, 网络流量审计, 逆向工具, 隐私保护, 隐私保护