op4 — 安全终端信使
op4 是一款用 Rust 编写的、基于终端的加密消息应用。 它提供使用后量子密码学的端到端加密私密消息, 并完全通过 Tor 网络路由,因此你的消息内容和 IP 地址 都不会暴露给任何人——甚至包括你在交谈的对象。
op4 让两个人无需任何一方泄露 IP 地址或真实身份即可 交换私密消息。每条消息都:
op4 完全在终端中运行。它没有 GUI、没有浏览器组件, 也没有云账户。它唯一接触的外部进程是运行在你自己机器上的 Tor 守护进程。
所有下载选项 — AppImage、源码压缩包、克隆并构建,以及 自动化安装程序 — 均记录在 下载与安装指南 中。 最新版本可在 Releases 页面 获取。
在 Debian 和 Ubuntu 上,install/setup.sh 一条命令即可处理所有事项:
Rust 工具链、构建依赖、Tor、控制端口配置、二进制编译、
系统用户、数据目录和 AppArmor 配置文件。
git clone https://github.com/Opfour/op4.git
cd op4
sudo bash install/setup.sh
脚本运行结束后,你必须注销并重新登录后才能运行 op4。 安装程序会将你的用户添加到
debian-tor组, 以便读取 Tor 的 cookie 文件。Linux 不会将组变更应用到 已经打开的会话——需要重新登录。跳过此步骤会导致 op4 启动时失败,并显示:
Permission denied reading /run/tor/control.authcookie
然后,请验证脚本打印的源哈希是否与你所用版本的 公开发布哈希一致,然后再信任该二进制文件。
op4 启动时会打印一个源哈希,涵盖所有 Rust 源文件、
Cargo.toml、Cargo.lock 和 build.rs。请将其与下面
你所安装版本对应的值进行比较。
你也可以在不启动完整应用的情况下检查它:
op4 --print-hash
如果哈希不匹配,请不要使用该二进制文件——它要么由不同的提交构建, 要么已被篡改。
先安装依赖,然后运行脚本:
Rust 工具链(通过 rust-toolchain.toml 固定到 1.89.0):
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source "$HOME/.cargo/env"
Tor 和构建依赖:
# Fedora
sudo dnf install tor gcc pkg-config openssl-devel
# Arch
sudo pacman -S tor base-devel pkg-config openssl
配置 Tor 控制端口 — 添加到 /etc/tor/torrc:
ControlPort 9051
CookieAuthentication 1
sudo systemctl restart tor
将你的用户添加到 Tor 组:
sudo usermod -aG tor $USER # Fedora / Arch
完成此步骤后,你必须注销并重新登录。 组成员变更 不会应用于当前的活跃会话。在此之前,op4 会因
Permission denied reading /run/tor/control.authcookie而失败。如果不想完全注销,可以通过以下命令应用变更:
newgrp tor
构建并安装:
git clone https://github.com/Opfour/op4.git
cd op4
cargo build --release
sudo bash install/setup.sh
op4
# or, without system install:
./target/release/op4
首次启动时,op4 会引导你设置一个普通口令和一个胁迫口令,
然后生成你的身份密钥。你的保险库存储
在 ~/.local/share/op4/vault.op4。
最低内核:4.15(建议 5.4+)。架构:x86-64 (aarch64 应该可以工作,但尚未测试)。
双方都需要安装 op4、运行 Tor,并解锁各自的保险库。 交换过程是非对称的:一方先发送自己的联系代码, 另一方添加该代码,然后发送第一条消息, 这条消息会作为待处理请求到达,由先发送代码的一方接受。
首次运行时,op4 会提示输入普通口令和胁迫口令,
然后生成你的身份密钥。此过程只会发生一次。
你的保险库存储在 ~/.local/share/op4/vault.op4。
$ op4
你的联系代码包含完整的公钥包和你的 .onion 地址。
对方需要它才能联系到你。
2 或 →)e 导出你的联系代码op4: 开头你的联系代码并非机密,可以公开分享。 它只包含你的公钥和 onion 地址——不含任何私密材料。
拿到对方的联系代码后:
a 添加联系人op4: 联系代码并按 Enter↑/↓,然后按 Enter)3 或 →)这条第一条消息会启动加密握手,并通过 Tor 投递到对方的
.onion 地址。对方会将其视为待处理联系人请求。
当有人向你发送第一条消息时,联系人标签页上会出现一个徽章, 显示有多少待处理的请求。
2)p 查看待处理请求Esc 拒绝并丢弃)接受后,Double Ratchet 将被初始化,对话会立即出现在消息标签页中。
在信任某个联系人之前,请确认对方的指纹与其自己屏幕上显示的指纹一致。 这可以防止在初始联系交换期间发生中间人攻击。
A3F2:91BC:…如果你认为自己的身份密钥可能已泄露:
4 或向右导航)r 轮换密钥op4 使用 Double Ratchet 协议(类似于 Signal 协议)来 实现前向保密。这意味着:
KEM 步骤按如下方式结合 X25519 和 ML-KEM-768:
shared_secret = HKDF(X25519_ss || MLKEM_ss)
攻击者必须同时破解两种算法才能破坏密钥交换。 这可以抵御量子对手(ML-KEM-768),同时在 ML-KEM-768 存在未知缺陷时 仍能抵御经典攻击(X25519 回退)。
消息使用 HMAC-SHA256 进行认证,密钥从共享棘轮状态派生而来。 由于双方持有相同的 HMAC 密钥,任何一方都可以生成任意的 MAC。 这与 OTR 和 Signal 使用的可否认性属性相同: 在法庭程序中,消息无法在密码学上归因于特定发送者。
位于 ~/.local/share/op4/vault.op4 的保险库文件存储所有联系人、
对话和身份密钥。它由两个独立的、通过 Argon2id 派生的密钥保护:
op4 会为你的收件箱创建一个 Tor v3 隐藏服务。
你的 .onion 地址由你的身份密钥确定性派生(通过 HKDF),
因此在重启后保持稳定,无需存储单独的密钥。
出站消息通过 Tor SOCKS5 代理发送。
你的真实 IP 地址永远不会出现在与 op4 相关的任何网络数据包中。
掩护流量(以泊松分布发送给自己的虚假消息,平均间隔 30 秒) 可防止网络观察者通过观察流量大小来推断你是否正在积极 与某人通信。
apparmor/op4.profile)— 将文件系统访问限制为仅保险库目录、终端设备和 Tor。┌─────────────────────────────────────────────────────────────┐
│ op4 process │
│ │
│ ┌──────────┐ ┌──────────────────┐ ┌────────────────┐ │
│ │ TUI │ │ Double Ratchet │ │ Tor Transport │ │
│ │ (ratatui)│──▶│ + Hybrid PQ │──▶│ nym_client.rs │ │
│ │ │ │ Crypto │ │ │ │
│ └──────────┘ └──────────────────┘ └───────┬────────┘ │
│ │ │
│ ┌──────────────────────────────┐ │ │
│ │ Encrypted Vault │ SOCKS5 / control port │
│ │ ~/.local/share/op4/vault.op4│ │ │
│ └──────────────────────────────┘ │ │
└────────────────────────────────────────────────┼───────────┘
│
┌────────────▼────────────┐
│ Tor daemon │
│ 127.0.0.1:9050 (SOCKS) │
│ 127.0.0.1:9051 (ctrl) │
└────────────┬────────────┘
│
Tor network
│
┌────────────▼────────────┐
│ Peer's .onion address │
│ (their hidden service) │
└─────────────────────────┘
op4/
├── src/
│ ├── main.rs Entry point, startup sequence
│ ├── error.rs Unified error types
│ ├── crypto/
│ │ ├── keys.rs Hybrid KEM + signature keypairs
│ │ ├── primitives.rs AEAD, HKDF, HMAC, Argon2id
│ │ ├── ratchet.rs Double Ratchet implementation
│ │ ├── hmac_auth.rs Deniable authentication tags
│ │ └── handshake.rs Initial key agreement (X3DH-style)
│ ├── network/
│ │ ├── nym_client.rs Tor hidden-service transport
│ │ └── message.rs Wire message format + padding
│ ├── storage/
│ │ └── vault.rs Encrypted vault (Argon2id + AEAD)
│ ├── identity/
│ │ ├── profile.rs Contact codes, stored contacts
│ │ └── revocation.rs Key revocation records
│ ├── hardening/
│ │ ├── memory.rs mlockall, RLIMIT_CORE, dumpable
│ │ └── seccomp.rs seccomp-bpf syscall filter
│ └── ui/
│ ├── app.rs TUI event loop and state machine
│ ├── contacts.rs Contacts tab rendering
│ ├── conversation.rs Messages tab rendering
│ ├── settings.rs Settings tab rendering
│ ├── duress.rs Duress inbox rendering
│ ├── input.rs Input sanitization (CSI/OSC strip)
│ └── passphrase.rs Secure passphrase prompts
├── apparmor/
│ └── op4.profile AppArmor MAC profile
├── install/
│ └── setup.sh System installation script
├── build.rs Embeds source hash at compile time
├── deny.toml cargo-deny licence + advisory rules
├── rust-toolchain.toml Pins Rust 1.89.0
└── docs/ This documentation
版本:0.2.0-dev(预发布)
op4 正在积极开发中。以下层已完成并通过测试:
所有层现已端到端打通:
PublicKeyBundle(你的完整公钥集 + onion 地址)。所有已知限制均已解决。该应用目前处于 0.2.0-dev 的功能完整状态:
HMAC 可否认认证已完全打通。每条出站数据消息都携带一个 HMAC-SHA256 标签,该标签使用每条消息的棘轮密钥对 (conversation_id || message_counter || ciphertext) 计算。入站消息在接受前会经过验证;为了向后兼容,来自旧版本对端的零填充标签会被容忍。
消息历史跨重启持久化。 完整对话日志使用每对话 HKDF 派生密钥加密,并存储在保险库的 message_log_ct 字段中。打开对话时从保险库加载消息,每次发送或接收后写回。
来自未知方的入站联系人请求会排队而不会丢弃。当有待处理请求时,联系人标签页会显示徽章。按 [p] 查看:你会看到发送者的指纹和对方的第一条消息,输入名字后按 Enter 接受(或按 Esc 拒绝)。接受后联系人被添加,Double Ratchet 被初始化,初始消息保存到保险库。
胁迫保险库在保存时保持不变。 保险库文件格式(v2)在头部存储精确的密文长度,因此 AEAD 解密操作的是真实字节,而不是零填充部分。每次调用 save() 时,加密的胁迫部分都会原样存储,使胁迫口令无限期有效。
专用 Double Ratchet 引导密钥。 首次运行时生成单独的 X25519 密钥对(identity_ratchet_secret),并作为 ratchet_pub 包含在联系代码中。Alice 的棘轮用 Bob 的 ratchet_pub 而不是他的 KEM 身份密钥初始化,从而分离了密钥角色。
设置标签页完全可用。 Tor SOCKS5 地址和自动删除阈值可以内联编辑。密钥轮换(生成新密钥对、向所有联系人广播签署的撤销证书、刷新导出代码)和密钥报废撤销均已打通并可用。
密钥撤销端到端打通。 RevocationCertificate 结构体使用混合 Ed25519+ML-DSA-65 密钥对签署,并通过 Tor 以 WireMessageType::Revocation 消息发送给所有联系人。
| 版本 | 源哈希 |
|---|
0.3.0 | 80820cb41a63575d2c139dadd425d13d1e87e62a9d60200ae7b894ae2e9ad8ed |
0.3.1 | 48115efb12747fa78b627ddbf7a56c46169f59e777d7d7508941bf89e4fe7521 |
0.2.0-dev | 35740577f6c4a4f19c5a08fe85b1f78a10347f2ba9dd7642d126552266bfa5a5 |
0.1.0 | e1a94761c7d3fa589ba892b47d5295aa417f95aee126809d51a7e7fb7e78982c |
| 发行版 | 状态 |
|---|
| Ubuntu 22.04 / 24.04 | 支持 |
| Debian 12 | 支持 |
| Fedora 39+ | 支持 |
| Arch Linux(当前) | 支持 |
| Tails OS | 支持(安装指南) |
| macOS / Windows / WSL1 | 不支持 |
| 按键 | 操作 |
|---|
1 / ← → | 切换标签页(联系人 / 消息 / 设置) |
↑ ↓ | 移动选择 |
Enter | 打开对话 / 确认 |
Esc | 取消 / 返回 |
e | 导出你的联系代码(联系人标签页) |
a | 添加联系人(联系人标签页) |
p | 查看待处理请求(联系人标签页) |
d | 删除选中的联系人(联系人标签页) |
r | 轮换你的密钥(设置标签页) |
q | 退出 |
| 用途 | 算法 |
|---|
| 保险库密钥派生 | Argon2id (m=64 MiB, t=3, p=1) |
| 保险库加密 | ChaCha20-Poly1305 (256-bit key, 96-bit nonce) |
| 消息加密 | ChaCha20-Poly1305(来自棘轮的单条消息密钥) |
| 密钥派生(棘轮) | HKDF-SHA256 |
| 可否认认证 | HMAC-SHA256 |
| 经典密钥交换 | X25519 |
| 后量子密钥交换 | ML-KEM-768 (FIPS 203) |
| 经典签名 | Ed25519 |
| 后量子签名 | ML-DSA-65 (FIPS 204) |
| 传输匿名 | Tor v3 hidden services (.onion) |
