PrivChat 是一款面向 Android 的点对点加密通讯工具。无需创建账号,无需提供手机号,也没有任何公司保管你的对话——包括我们在内。两部手机通过 Tor 网络直接交谈。
大多数通讯工具既是加密的又是中心化的:你的话语受到保护,但公司仍然能看到你和谁交谈、何时、多频繁。那份记录往往比话语本身更能暴露你。PrivChat 直接移除了那家公司,而不是要求你信任它。
当你写一条消息时,你的手机会把它加密,交给 Tor 网络,由后者让它经过一条由世界各地独立志愿者运行的中继链条。每个中继只知道上一跳和下一跳。第一个中继知道你在发送某样东西,却不知道发给谁;最后一个中继知道它要去哪里,却不知道是谁发的。沿途没有人能读到它,因为密钥只存在于那两部手机上。
你的网络服务商也处在同样的位置。它能看到你连接到 Tor 网络——对任何建立在 Tor 之上的工具来说,这一点都无法避免——但它读不到你所写内容的一个字,而这并非出于善意:消息在离开你手机时就已经加密,因此任何可读的内容都不会经过它的网络。你所连接的 wifi,以及任何监视线路的人,也都一样。
这里没有收件箱,没有队列,也没有云。如果对方离线,消息会留在你的手机上,稍后再试。任何东西都绝不会寄存在属于别人的机器上。
消息会经过若干层,每一层解决一个不同的问题。
密钥不会重复使用。每条消息都用它自己的密钥加密,即时派生、立即丢弃,链条随着双向的每一条消息向前推进。如果某一把密钥曾被攻破,它也只能打开一条消息——而不是整段对话。而一旦两部手机再次互发消息,链条便自我修复:即便攻击者曾以某种方式掌握了当前状态,也会被重新挡在门外。
把话语加密是容易的部分。通常泄露的是围绕它们的一切:谁、何时、多频繁、多长。PrivChat 把每条消息包进一个密封的信封,其中唯一可读的部分是一把随机的一次性密钥,而加密本身的内部路由头也同样被加密——因此来自同一个人的两个数据包无法被认出是属于一起的。
一个字母的回复和一大段文字产生的数据包大小完全相同,因此长度什么都不透露。在此之上,应用还会以随机间隔发送诱饵数据包,与真实数据包无从区分。其结果才是关键所在:监视你连接的观察者根本无法判断你是否正在进行对话。
有一种攻击是你事后无法防御的。对手可以在今天记录下你的加密流量,直接把它存起来。没有什么能阻止这一点。如果多年以后,量子计算机能够攻破 2026 年所用的密钥交换,那么他们存下的一切都会变得可读——而且是追溯性的,届时你对此无能为力,因为记录早已发生。
PrivChat 的密钥协商把经典算法(X25519)与 ML-KEM-768——NIST 于 2024 年标准化的后量子算法——结合起来。两个秘密被混合在一起,因此攻击者必须同时攻破两者——而那个共享秘密会为整段对话播下种子,双向都是,直到对话结束为止。
这对恰恰需要这类应用的人最为重要:你今天所说的话,在十五年后仍然值得保护。
消息、联系人、附件以及密钥本身,全都在静态时加密,用一把保存在 Android 密钥库中、并与设备硬件绑定的密钥。你可以加设一个 PIN 码,那么密钥就需要两半——你的 PIN 码和一个设备秘密——因此没有你,就连手机自己也打不开它自己的存储。
应用把自己排除在 Android 的自动备份之外,因此你的对话绝不会被上传到任何云端,连你自己的云也不会。阅后即焚消息会在 24 小时后自我删除,而“清除身份并重新开始”会销毁密钥,而不只是删除文件:在那之后,即便手机在手,旧数据也无法恢复。
其架构是点对点的,而这正是决定本页其余一切是否成立的部分。每部手机都运行自己的 Tor 洋葱服务,直接与另一部交谈。没有我们的中继,没有消息队列,没有账号数据库——因此没有任何地方能够堆积起谁与谁交谈的记录,哪怕对于前来索取它的人也是如此。移除服务器并不是加装在加密之上的一个功能。它正是让加密值得拥有的东西。
在此之上运行的,是政府与业界共同选定的那一套标准。这里没有任何东西是自制的,每一块都有公开的规范——链接指向规范本身,而不是指向我们。
| 用途 | 所使用的 |
|---|---|
| 架构 | 点对点:每部手机都是它自己的 Tor v3 洋葱服务,中间没有服务器 |
| 密钥协商 | PQXDH — X25519 与 ML-KEM-768 (FIPS 203) 结合 |
| 密钥更新 | Double Ratchet, 带加密的头部 |
| 消息加密 | ChaCha20-Poly1305 |
| 签名 | Ed25519 |
| 密钥派生 | HKDF-SHA256 |
| PIN 码派生 | Argon2id |
| 本地数据库 | SQLCipher (AES-256) |
| 传输 | Tor,通过 arti 实现 |
联系人由一个你可以当面读出来核对的指纹来标识,这样你就能确认你正在交谈的是你以为的那个人,而不是拦截了这次介绍的某个人。
PrivChat 是免费的,没有广告,也不收集任何可供出售的东西。如果你想支持它,这里只有以下两个地址。发送任何东西之前,请核对指纹。
为什么指纹很重要。捐赠地址以明文写在应用内部。用一个不同的地址重新构建应用,正是针对接受捐赠的应用的经典欺诈:你复制了一个并非我们的地址,而你根本无从察觉。
应用会在地址旁显示一个短指纹。如果它与本页上的一致,那么你这份应用副本中的地址就是真的。这与应用为验证一位联系人而请你做的动作是同一个。
45hRduLUQD5Ek4qGgHTuWAZnncwroMET1WsLUDC9AF6DNSt5qMP1Fk7WUsN4EwzJdA1ypfL7TtJQQ8uqutAJWwJy5jzp8Pa
指纹:1D63 68D5 7653 1887
sp1qqf2jvtz0k7rsy7f0cka9ejz6e4lmakz6v9zgae02ks0qpck3a6dxzqn73fp9gj6y632q8th2nfv2lv7rua49s5unzjpau3ahp29ssw689vwu9ksy
指纹:63BB FA03 F806 BC55
因为在公开链上,每个捐赠者都会付到同一个地方,而那会永远可见。任何人都能拉取出向一个加密通讯应用捐过款的人的名单。那份名单正是这个应用存在的意义所在——去阻止它出现——所以我们不会为了收取捐赠而亲手制造它。
静默支付地址的运作方式不同:你的钱包会派生出一个只有我们才能动用的全新目标地址,因此链上没有任何东西把这些捐赠彼此关联。它需要一个支持 BIP-352 的钱包。
上面这两个指纹也以一份签名声明的形式发布,这样一来,要改动它们就不只是攻破本网站那么简单——还得同时拿到我们的签名密钥。
签名声明:donations.txt
公钥:privchat-pgp.asc
密钥指纹:
BC8D E53F D8D1 6F63 AD8A 33EA 10EC 8069 37D6 8502
核对方法:导入该密钥,然后运行 gpg --verify donations.txt。它报告的密钥指纹必须与上面的一致。
同一个密钥指纹也发布在我们的 Google Play 页面上。它们是两个各自独立、由不同公司掌管的地方:一个伪造的指纹必须同时出现在两处并保持一致。如果两者有朝一日不一致,什么都不要发送,并写信给我们。
初次使用?如何使用 PrivChat 会带你走一遍添加第一位联系人、核对指纹,以及各种消息状态的含义。