工作原理

Crocodile 如何让你的对话只属于你

用通俗的语言带你了解架构和协议。每一章都从核心思路讲起;展开“深入底层”可查看技术细节。

章节 1

四类参与者

Crocodile 对工作进行了分工:只有和你对话的人能看到你说的话,而由陌生人运行的部分永远看不到。

你的应用

保存你的密钥,加密你发送的一切,解密你收到的一切。你的消息记录就保存在这里,别处都没有。

知道: 你收发的一切:这本来就是你的。

主持者

在每个语音房间或空间里,会选出一位成员的应用,把加密流量转发给其他人。它和其他人一样,只是一名成员。

知道: 成员的 IP 地址和谁在说话,但永远不知道说了什么。

协调服务器

由志愿者运行的交换台:保存个人资料和空间,告知谁在线,并选出主持者。它们共同组成一个网络。

知道: 个人资料、成员身份和谁在线,但永远不知道说了什么。

目录

协调服务器的电话簿,让新应用知道从哪里开始。它对人一无所知。

知道: 只知道服务器列表。

章节 2

你的账号是密钥,而不是密码

安装 Crocodile 时,你的应用会在电脑上生成一个 32 字节的随机秘密。由它产生两把密钥:一把用于为你发布的内容签名,另一把用于接收加密消息。你的用户 ID 是签名密钥的指纹。

由于 ID 是从密钥计算出来的,服务器无法换上另一把密钥来冒充你。没有可被窃取的密码,也没有可以骗过客服来执行的重置。这个秘密会作为恢复密钥向你显示一次,并用系统钥匙串加密保存在你的设备上。

深入底层
  • 从 32 字节的种子派生出一把 Ed25519 签名密钥和一把 X25519 加密密钥。用户 ID 是 base32(SHA-256(签名公钥)) 的前 26 个字符。
  • 每台设备都会发布一份已签名的设备记录,附带每周轮换的预密钥包(X25519 + ML-KEM-768)。旧的预密钥秘密在宽限期后删除。
  • 安全码让两个人可以通过其他渠道比对彼此的密钥,和其他安全通讯工具一样。
  • 本地数据(身份、预密钥、历史记录)使用受操作系统钥匙串保护的密钥加密存储。

章节 3

找到最快的服务器

你的应用从目录下载协调服务器列表,测量每台服务器的响应速度,并连接最快的一台。第二台作为备用;如果你的服务器宕机,应用会立即切换。

在一切开始之前,服务器先证明自己的身份,应用和服务器为这次连接协商密钥。此后,即使是它们交换的元数据,也会在 HTTPS 之上再加密一层,因此在家用服务器上运行也同样安全。

深入底层
  • 目录列出的每台服务器都由该服务器自己签名,地址经过隐藏。应用在使用任何条目之前都会验证签名。
  • 服务器签名的问候消息携带一个新的混合密钥交换提议(X25519 + ML-KEM-768)。应用用目录中的密钥验证它,作出回应,并对完整记录签名。之后的每一帧都用 AES-256-GCM 加密并填充。
  • 服务器还会在两个端口上响应 STUN,因此应用无需询问 Google 或 Cloudflare 就能得知自己的公网地址和 NAT 类型。

章节 4

无法在你身上撒谎的服务器

你的个人资料、你创建的空间、空间的邀请以及成员名单,都是由作者签名的小记录。服务器保存并分享它们,每台服务器和每个应用都会验证签名。服务器可以拒绝转发某条记录,但无法修改或捏造它。

协调服务器会互相发现并组成一个网络。每条记录根据哈希保存在几台服务器上,这些服务器相互复制变更,因此任何一台服务器宕机时,网络都能继续运行。

深入底层
  • 记录类型:个人资料、密封的好友列表、空间、邀请、成员、设备和便笺。每种记录都有允许写入它的作者;验证(签名、权限、“最后写入者胜出”的版本)在服务器和客户端上完全相同。
  • 好友列表只为所有者自己的设备加密,好友请求以不注明发送者的密封便笺传递,因此服务器不知道谁和谁是朋友。
  • 每条记录归属于其分片在一致性哈希环上的前几台服务器。所有者复制写入,用序列游标补齐缺失内容,并在服务器加入和离开时移交记录。

章节 5

一位朋友主持,一位备用在旁

当有人加入语音房间或打开空间时,协调服务器会查看每个人的连接情况(网络的开放程度、上传速度、电脑性能、是否在用电池),并选出最合适的成员担任主持者。次优者作为备用。

每个人都连接到主持者的应用,由它转发加密音频。为了减轻负担,它只向每位听众发送音量最大的几位发言者。音频在传输途中从不以明文出现:主持者只搬运密封的数据包。

如果主持者离开或无法连接,备用者会接替,所有人重新连接到它,通常没有人会察觉。

深入底层
  • 主持者在其应用内运行一个小型 SFU(selective forwarding unit,选择性转发单元)。每位成员与它建立一个 WebRTC 连接,包含一路上行音频轨道、五个下行发言者槽位和一个数据通道。
  • 发言者槽位根据 RFC 6464 音频电平头分配(“last-N”),序列号会被重写,使每个槽位保持为一条连续的流。
  • 提议和应答用身份密钥签名,签名覆盖会话、纪元、双方 ID 和 DTLS 指纹,因此协调服务器无法插在中间。
  • 每次更换主持者都会使纪元编号加一,旧的提议会被忽略。无法连接到主持者的成员会报告这一情况,当半数成员同意时,备用者接替。

章节 6

层层加密

一切在离开你的设备之前就已加密,只有对话中的人才持有密钥。下面是一条消息在途中经历的过程。

一条消息,四层保护

你的应用对消息签名,让别人能证明它来自你;对它进行填充,使长度不泄露任何信息;用只有对话成员才持有的密钥加密;再通过本身也加密的连接发送。无论途中是谁,看到的都只是标准大小的乱码。

为量子计算机做好准备

密钥交换采用混合方式:经过实战检验的经典方法 X25519,加上新的后量子标准 ML-KEM-768。攻击者必须同时攻破两者。这很重要,因为有人可能今天记录下加密流量,等待量子计算机来解密。

不断前进的密钥

每位成员的密钥像棘轮一样转动:每条消息之后,它都会被一条只能向前的链上的下一把密钥取代,旧密钥随即删除。今天偷到密钥的人无法读取昨天的消息。每 30 分钟以及每当有人离开时,所有人都会用新的随机密钥开启新链,因此被盗的密钥也会很快失效。

语音,逐帧加密

你的声音被切成小帧,大约每秒五十帧,在离开麦克风之后、到达网络之前就被加密。无法加密的帧会被丢弃,绝不会以明文发送。语音使用恒定码率,因此数据包大小不会泄露你说了什么。

深入底层
  • 成对秘密(发送者密钥分发、历史同步、设备关联、服务器通道)通过 HKDF-SHA256 将 X25519 和 ML-KEM-768(FIPS 203)结合。
  • 发送者密钥有两条 HKDF 链:文字链在每条消息后推进,语音链每 30 秒推进一次。密钥每 30 分钟以及有人离开时更换,并且只发送给应用自己通过签名记录确认过成员身份的设备。
  • 语音:Encoded Transform 工作线程用 AES-256-GCM 加密每个 Opus 帧,并附加经过认证的 SFrame 风格后缀(密钥 ID、代数、计数器)。
  • 文字:由作者签名(Ed25519),用 Padmé 填充,并用文字链加密。
  • 发送给某台设备的密封盒使用该设备当前的预密钥,并由发送者签名,因此即使是发给离线设备的消息也具有前向保密性。

章节 7

当无法直接连接时

有些网络,例如办公室或大学里严格的防火墙,会阻止电脑之间的直接连接。出现这种情况时,Crocodile 会告诉你,你可以允许一台协调服务器为你中继流量。

中继转发的是已经端到端加密的数据包:它能看到包的大小和时间,但看不到内容。每次许可持续一小时,只有在仍然需要时才会续期。

深入底层
  • 中继是标准的 TURN(RFC 5766),运行在协调服务器的 UDP 端口上,使用短期凭据。服务器会限制可使用它的人数。
  • 连接时,应用会对照两个 STUN 端口测试自己的网络,将其归类为开放、受限(对称型 NAT)或被阻止,并在需要时建议使用中继。
  • 每次连接都会记录四个步骤(提议、应答、网络路径、加密通道),因此出现故障时,应用能指出问题出在哪里。

章节 8

总能送达的消息

没有任何服务器保存你的历史记录,因此 Crocodile 应用之间相互传递消息。下面是你给离线的人发消息时发生的事情。

  1. 在你这里等待

    消息进入应用的发件箱,并显示一个小时钟。

  2. 朋友上线

    双方都在线时,你的应用会立即送出消息,并为对方的设备密封。

  3. 已确认

    对方的应用确认收到,时钟随即消失。在空间中,错过消息的成员会从主持者和备用者那里补齐。

  4. 或者使用邮箱

    如果你愿意,服务器可以替你保存私信最多 7 天,并为每台设备单独密封,服务器自己无法读取,送达后即删除。

章节 9

添加一台电脑

你的新电脑会显示一个短代码。在已经登录的电脑上输入它,然后确认两块屏幕显示相同的六位安全码。如果一致,你的账号会以加密方式传过去,新设备即可使用。

安全码同时涵盖两台设备的密钥,因此如果有人试图在途中替换其中一把,安全码就会不同,你会发现的。

术语表

你在安全类文章中会遇到的术语,每个用一两句话解释。

端到端加密
只有发送者和接收者持有密钥。中间传递消息的一切,包括服务器,看到的都只是乱码。
点对点
应用之间直接连接,而不是连接到中央服务器。
后量子密码学
旨在抵御未来量子计算机的加密,这类计算机可能破解当今互联网大部分使用的方法。ML-KEM 是 NIST 于 2024 年发布的标准。
前向保密
今天密钥被盗,也无法打开旧消息,因为当时使用的密钥已被删除。
泄露后安全
密钥被盗后,新的随机密钥会很快把窃贼重新拒之门外。在 Crocodile 中,这会在 30 分钟内发生,或在有人离开时立即发生。
数字签名
用私钥制作的数学印章。任何人都可以用公钥验证它,没有私钥的人无法伪造。
NAT、STUN 和 TURN
家用路由器把电脑隐藏在一个公网地址之后(NAT)。STUN 帮助应用得知自己的公网地址以便直接连接,TURN 则在无法直连时中继流量。
SFU
选择性转发单元(selective forwarding unit),把每位发言者的音频转发给每位听众,不混音也不解密。在 Crocodile 中,它运行在主持者的应用里。
元数据
关于对话的数据,而不是对话内容:谁和谁、何时、多久通信一次。Crocodile 完全加密内容并尽量减少元数据,但服务器仍能看到一部分。

阅读完整的架构文档(英文)