消息通过 libp2p 在节点之间直接传输,并在离开你的设备之前使用 Signal 风格的 Olm/Megolm 协议(通过 vodozemac)加密。唯一涉及的服务器是一个小型目录,帮助节点找到彼此的当前地址。它永远看不到消息内容,而且可以用一条命令清除。
有关实际防护的内容以及方式,请参阅 docs/THREAT_MODEL.md 和
docs/SECURITY.md。
首次运行 —— 只需选择一个名称;无需其他设置。
会话 —— 群组栏、联系人列表和端到端加密聊天面板。
设置 —— 麦克风灵敏度、按键通话、登录时启动、网络可达性。
crates/directory-server)仅将用户 ID 映射到当前网络地址,
除此之外不做任何事情。它在结构上无法读取消息内容:
其 Cargo.toml 甚至不依赖任何知道如何读取消息内容的 crate。这个应用中有两种身份,它们被刻意分开:
identity::Identity)。你的公开“用户 ID”就是该密钥的指纹(wire_proto::user_id_from_ed25519)。任何服务器都无法签发或吊销它,因为它的创建过程不涉及任何服务器。PeerId),仅用于传输层。它可以在重启之间变化,而完全不影响你的聊天身份;两者仅通过你自行签名的在线状态记录绑定在一起。找到某人并真正与他们交谈是两个不同的步骤:``` ┌────────────────────────┐ │ directory server │ │ (axum + one SQLite │ │ file: users, │ │ presence, group │ │ rosters. Never │ │ message content.) │ └─────────┬───────────────┘ 1. "where is bob │ 2. "here's my current right now?" │ address" (signed, │ expires in minutes) ┌─────────┴───────────────┐ ▼ ▼ ┌───────┐ 3. direct libp2p ┌───────┐ │ alice │◄──── connection ────►│ bob │ └───────┘ (Noise + Olm/ └───────┘ Megolm encrypted)
1. Alice 通过 Bob 的用户 ID 在目录中查找他。这会返回他的
公钥以及他最后通告的网络地址。这就是目录所持有的全部内容:
公钥、显示名称、组成员列表,
以及短期有效的地址通告
(`crates/directory-server`)。
2. Alice 直接通过 libp2p(QUIC 或 TCP+Noise,带中继 +
NAT 打洞,用于 NAT 后的对等方;参见 `crates/net`)呼叫 Bob。目录从
此刻起完全不再参与。
3. 实际消息会使用 **Olm**(用于 1:1 聊天)或
**Megolm**(用于群组,`crates/crypto-session`),这是一种 Double-Ratchet 风格
方案,每条消息在放到该 libp2p 连接之前
都有自己的密钥。没有服务器端收件箱:如果 Bob 离线,
消息会在本地等待并重试,而不是存储在任何其他人的
基础设施上。
以上所有内容均由 `crates/core` 的 `AppService` 编排,它
是 Tauri 应用的 Rust 后端(`apps/desktop/src-tauri`)实际调用的对象;
UI 从不直接与网络通信。
## 项目布局```
crates/
wire-proto shared signed-request types for the directory API
identity vodozemac identity, OS-keychain key management
storage local encrypted store (contacts, messages, groups)
net libp2p transport + directory HTTP client
crypto-session Olm (1:1) / Megolm (group) session management
core orchestrates the above into `AppService` / `ChatNode`
directory-server the one server component (axum + SQLite)
apps/desktop the Tauri + React app
scripts/ build + backend-deployment scripts (§2, §5)
你在每个平台上都需要 Rust 和 Node.js,此外还需要 Tauri 用于构建原生窗口的、特定于平台的
工具链。storage 和 directory-server 还会从源码捆绑编译 SQLite,这需要一个普通的 C 编译器(本项目中
任何地方都不需要 OpenSSL 或其他原生加密库)。
所有平台通用: