安全模型
本页如实说明协议第 3 版(rChat 2.0.0)能防护和不能防护的内容,是 rChat 威胁模型的摘要。完整的威胁模型和详细内容见白皮书。
受保护的内容
Section titled “受保护的内容”- 消息内容。 消息在手机上加密,密钥由混合握手协商(X25519 与后量子的 ML-KEM-768 相结合),并由 Double Ratchet 推进,加密算法为 XChaCha20-Poly1305。中继只转发它无法解密的密文。
- 面向未来量子计算机的已记录流量。 每个会话和每个消息请求都在端到端层面把 ML-KEM-768 秘密与 X25519 结合,因此今天记录流量、日后拥有量子计算机的人仍必须同时攻破两者。与中继之间的连接也使用混合后量子密钥交换(X25519MLKEM768),以同样方式保护链路承载的元数据;消息内容并不依赖它。只有密钥交换是后量子的:证明身份的签名(Ed25519,以及设备密钥的 P-256)、中继的证书和身份以及连接证明仍是经典算法,今天无法伪造,但无法抵御在您连接时已经拥有量子计算机的攻击者。
- 消息的前向保密。 每条消息使用新的密钥,日后泄露的密钥不会暴露之前的消息。每次握手的后量子部分使用用后即擦除的新密钥。这不包括请求及其附带的第一条消息(见下文)。
- 完整性与绑定。 每条消息都会认证其头部和双方的身份密钥,因此只能由它所属的这一对用户解密。
- 传输。 连接只使用 TLS 1.3,不支持 TLS 1.2,也没有明文回退(见 TLS 与证书)。
- 日志。 在默认级别下,中继不记录任何标识符、IP 地址或内容(见中继记录与存储的内容)。
- 签名的密钥。 每个账户的密钥(身份密钥、协商密钥和 ML-KEM 密钥)都由其身份密钥签名。rChat 拒绝用未签名的密钥建立会话,因此中继无法替换成自己的密钥。每个建立会话的请求还会对自己的一次性密钥签名,因此中继无法塞入一个它能解密的后量子密钥。
- 与 TLS 会话绑定的证明。 应用发布密钥时,会把中继新给出的挑战值与从 TLS 会话中取得的值(TLS 导出值)一起签名。中继只向证明了该身份的连接路由消息、投递排队的消息。复制到另一个连接上的证明会失败,恢复(resume)的 TLS 连接也要重新证明。这也是 TLS 必须在中继上终止 的原因(见 TCP 前端部署)。
- 固定即接受。 当您通过扫描二维码添加某人时,rChat 会记住对方的密钥,并且不会在其他密钥下与对方通信。不匹配时会显示 “Keys don’t match”,并保持到您再次扫描对方的二维码为止。联系人二维码也携带后量子密钥,因此大小约 1.7 KB,旧版本的二维码会被拒绝。
- 首次使用。 如果对方是通过请求首次联系您的,rChat 无法判断这个密钥背后是谁。联系人信息会显示 “Keys from their first message”。当面扫描对方的二维码,或核对安全码,才能确认。
- 安全码。 您可以与联系人当面或通过电话核对一个 60 位的安全码,确认双方持有的都是对方真实的密钥。一部手机可以把它显示为二维码,由另一部手机扫描。如果对方的密钥日后发生变化,“已核对” 标记会被移除。安全码没有因协议第 3 版而改变。
- 密钥轮换。 如果您轮换密钥,只有当通知由您之前的密钥签名时,联系人才会自动跟随;因此任何窃取了您之前密钥的人也能这样做。轮换无法找回被盗的账户:请改用 Reset Identity。
- 保存的会话。 每部手机都会保存会话的加密状态,用只有这部手机能使用的密钥封存,并排除在备份之外。应用重启不会丢失中继已接受的任何消息(正在移交的消息除外),重放的消息也绝不会被解密两次。中继重启会丢失它在内存中保存的消息,除非运营者开启了加密持久化。
- 真实的状态。 Sent 表示中继已接收消息。Delivered 表示联系人的手机已保存它,这由中继无法伪造的端到端加密回执报告。见送达与恢复。
- 丢失的状态在会话内部报告。 当手机丢失会话(重装、换新手机)时,它会在用固定密钥建立的新会话中告诉每位联系人哪些消息无法读取。中继无法伪造这个通知,只能丢弃它,此时发送方会一直看到 Sent。
- 自动重发需要联系人的手机。 只有当通知由联系人的设备密钥签名时,消息才会自动重发:设备密钥保存在对方手机的安全硬件中(没有安全硬件时是软件密钥,见已知限制),只有在您当面扫描对方的二维码(或粘贴以添加一位全新联系人)时才会被固定。此外还要求自消息发出以来密钥没有变化、消息不超过 72 小时且从未送达,并且每位联系人每天最多自动重发 50 条。否则消息会显示 Not delivered,由您点按 Resend。只窃取了联系人账户密钥副本、却没有对方手机的人,无法让您的手机自动重发任何内容。
中继身份与邀请
Section titled “中继身份与邀请”加入中继的常用方式是它的 邀请:由中继运营者提供的一条链接或二维码,包含中继的地址和身份。rChat 会立即固定这个身份,因此连首次连接也经过检查。邀请包含中继的秘密地址,因此持有者能连接到中继,但绝不能阅读消息。
没有邀请时,rChat 会在首次连接后记住中继的身份;如果身份在没有旧身份签名移交的情况下发生变化,就会停止连接。首次连接必须被信任,除非您自己输入中继的身份并开启 Require a saved server identity。见中继身份。
只有双方都请求时,会话才会建立。持有您的二维码但尚未被您接受的人无法看到您是否在线,在您接受之前也收不到您的任何内容。他们的请求可以附带一条简短的第一条消息。
请求由 ML-KEM-768 与 X25519 共同封装,因此仅凭录下的数据,即使将来有量子计算机,也打不开它。请求及其第一条消息仍不具备前向保密。 它们使用由接收方长期密钥派生的密钥加密,因此记录了请求的人如果日后获得这些密钥,就能读取其中的第一条消息。
您与某人第一次会话之后,你们的手机会用一个只有你们两人能计算出的代码重新连接。它每 10 分钟都会变化,每次重新上线也会变化,中继只保存它的加扰形式;因此记录请求的中继无法凭这个代码把您相隔约 20 分钟以上的两次请求关联起来。会话从不按旧电路恢复。会话打开期间,中继的内存仍会把两位成员关联在一起(与以前一样)。两人都离开约 10 分钟后,中继保存的任何内容都不再指明这一对;等待中的盲化请求不指明任何人;也没有任何令牌或电路 ID 能把一次连接期间与下一次关联起来。
- 您的手机仍会指明要联系谁的情况: 首次联系、其中一方重装或换新手机之后、密钥轮换之后,以及作为后备,在整整一天都无法以盲化方式重新连接之后。中继每天最多能迫使每一对用户发出一次这样指明对象的请求。
- 限制。 实时观察运行中中继的人仍能看到两个账户在同一时刻相互连接。会话打开期间,中继在两个已知连接之间路由它,其内存把你们两人关联在一起。联系人能看出您已重新连接。时钟与中继相差超过 5 分钟的手机根本无法连接(手机通常会自动同步网络时间),因此任何两部已连接的手机在时间上都足够接近,无需指明对方即可重新连接。
- 填充是强制的。 每条消息和回执都会被填充到一个大小档位(256 B、1 KiB、4 KiB、16 KiB,之后以 64 KiB 递增),每个请求都正好是 5120 字节。指明对象的请求和盲化请求大小相同。中继仍能看到所属的大小档位。
- 回执 与消息一样端到端加密,并带有短暂的随机延迟、小批量发送。中继仍可能根据时间推断出发送了回执。
- 稳定流量 是一个可选设置,默认关闭。应用打开期间,它以固定节奏向随机选中的打开会话发送大小相同的数据包,从而减少消息时间所透露的信息。只有对方也使用时它才完全有效,照片、文件和语音消息不在其中发送。
- Extra traffic protection 是较轻的可选设置,默认关闭。它在应用打开时发送额外的虚拟流量,使中继稍难判断您何时在发消息。它不能隐藏时间,并且会让与您有打开会话的人看出 rChat 是否打开。开启稳定流量时由它取代。
- 重新连接 会恢复其 TLS 会话,因此看起来与其他回访的客户端一样。当第二次连接出示第一次连接得到的恢复票据时,网络观察者可以把相隔最多 12 小时的两次连接关联起来(票据只使用一次,且只保存在内存中)。
- 中继的伪装网站 让随意的扫描看不出端口上运行的是什么,从 2.0.0 起每个中继的伪装网站都不同(见配置指南)。坚决的主动探测者可以把它与真正的 Web 服务器区分开。rChat 的流量没有伪装成网页浏览器的流量。
中继能了解到什么
Section titled “中继能了解到什么”运行期间,中继能看到哪些账户在线、何时在线、来自哪个 IP 地址,以及其中哪两个账户之间有打开的会话。当两人首次连接,或其中一方换了新手机或更换密钥之后,它还能在最多十分钟内看到哪个账户在尝试联系哪个账户。它不会把这些写入日志。
- 它能看到打开会话中每个数据包的大小档位、时间和方向,包括请求被接受的那一刻。
- 等待离线用户的请求在内存中保存到送达为止,最多 72 小时。
- 发给离线用户的消息在内存中最多保存 72 小时,送达后即删除。它们按接收方存放;发送方的身份在加密消息内部。
- 后台检查看起来是一次没有会话的短连接。
- 中继不会收到任何关于密钥轮换的数据,但它通常能把轮换后的身份与旧身份关联起来,因为新身份会立即联系同一批人。
任何运营、查封或取得运行中中继 root 权限的人,都能从其内存中读出在线的账户以及其中哪些账户共享打开的会话。这是一种减少,而不是保护。
中继始终可以拒绝、丢弃、延迟或重新排序流量。它自身的防护见资源限制页面。以下缺口只涉及破坏投递,都无助于识别用户或阅读消息:
- 请求洪泛。 来自许多来源的持续请求洪泛可能把较早的请求挤出已满的请求存储区。工作量证明是未来的工作。
- 共享地址。 公平份额按 IPv4 地址或 IPv6 /48 计算,因此同一个运营商级 NAT 地址后面的许多用户共享一份,这个地址可能成为被削减的那一个。
- 慢速消费者骚扰。 已接受的联系人可以按速率限制的上限发送。跟不上的接收方会被断开,其消息保存在离线队列中。
- 离线队列被填满。 已接受的联系人可以在接收方离开期间填满其离线队列,于是其他发送方会被拒绝,直到接收方重新连接或消息过期。稳定流量的数据包最多只能占用其中一半。
- 设备被查封。 查封您已解锁手机的人,或连同密钥复制了应用文件的人,可以读取仍在中继上、用当前密钥加密的等待消息,以及之后的消息,直到双方手机完成一次新的密钥交换步骤。
- 没有安全硬件的手机。 在没有 Secure Enclave 的地方(较旧的 iOS 模拟器),设备密钥是 Keychain 中的软件密钥。从这样的设备同时提取账户密钥和该密钥,就能通过自动重发检查。对这样的联系人,联系人信息会显示 “Their device key isn’t stored in secure hardware.”。
- 新手机,旧设备密钥。 联系人换新手机后,在您扫描对方的新二维码之前,您保存的仍是其旧设备密钥,因此恢复会退回为点按 Resend。这种失败方式是安全的。
- 队列移交。 手机在中继向它移交等待消息时被终止,会丢失这些消息。手机不会向中继确认;发送方会一直看到 Sent,这是真实的。
- 回滚。 能写入应用文件的人可以把保存的状态回滚到旧副本。这属于设备被攻破,除 iOS 数据保护外没有额外防护。
- 计数被抬高。 伪造的数据包可以抬高接收方手机上”无法解密”的计数。这只是拒绝服务,并且有上限。
- 首次联系。 通过请求首次联系您的人,在您扫描其二维码或核对安全码之前,按首次使用信任。
- 消息发送方信封。 普通消息的外层信封只用 X25519 向中继隐藏发送方;后量子保护在会话本身和请求中。
- 限时消息与通知。 它们不涵盖的内容见媒体与限时消息和通知。
密钥透明、后量子签名、请求的工作量证明,以及可复现构建。