Updated at: 2024-11-26
我们一步步的来展开这个问题:
首先在当今基于 TCP/IP 的互联网,葫芦娃和蛇精必须分别有自己的 IP,以接入互联网。但是是网就意味着,葫芦娃或蛇精的消息,可能会经过很多网络节点才能达到对方,中间的网络节点可能是互联网提供商,也可能是 IM 服务提供商。如下图所示:
很明显,中间的节点都会看到这个消息,这肯定是葫芦娃和蛇精不期望的。所以他们两个就要考虑将消息加密后再进行传输。那么第二个问题来了。
所谓加密就是使用一个密钥将消息加密为密文,然后你可以将这个密文通过任何节点来传递都没有问题,只要节点无法获得密钥,也就无法解密密文拿到消息。也就是如下图所示:
那么第三个问题来了。
也就是要想在传输之前将消息加密,双方就得约定一个共同的密钥,一方使用此密钥将消息进行加密,然后密文传递过去,另一方获取密文后,使用相同的密钥进行解密,进而得到消息。
问题出在,双方如何约定这个共同的密钥?
目前 Signal 和 WhatsApp 使用 Diffie–Hellman key exchange 算法让葫芦娃和蛇精通过 Signal 和 WhatsApp 的服务器来协商此密钥。注意 DH 算法使用的非对称密钥,这个不是重点,大概流程如下图所示:
那么以上有什么问题?在很久以前,我记得使用 mutt(一个终端使用的文本邮件客户端)时,那时搞加密,双方要想安全的传递邮件,必须要通过安全的方式来互相分享双方的公钥,比如线下,因为任何经过第三方来进行公钥或私钥分享的方式都是不可靠的,包括第三方公钥服务器,在以前 Unix Hacker 文化盛行时,甚至大家必须要举行一些线下活动见面来互相分享公钥。
难道 Signal 和 WhatsApp 有什么新魔法来解决这个问题吗?经过研究他们的 paper 和 博客,发现是没有的。如果这个问题不可靠,那么 Signal 和 WhatsApp 中下一步的 X3DH,Double Ratchet Algorithm,前向加密等更复杂概念就都不再可靠。因为经过了 Signal 和 WhatsApp 的服务器这个第三方角色,这个第三方角色可以同时欺骗葫芦娃和蛇精。如下图所示:
也就是说,Signal 和 WhatsApp 的服务器可以分别生成两对公私钥,然后分别和葫芦娃和蛇精对接,进而分别生成与葫芦娃的最终密钥和与蛇精的最终密钥。而葫芦娃以为自己的生成的最终密钥是蛇精的,蛇精也以为自己生成的最终密钥是葫芦娃的。那么后续葫芦娃和蛇精通过 Signal 和 WhatsApp 的服务器进行传递加密消息时,Signal 和 WhatsApp 就可以解密传递的消息。
那么 Signal 和 WhatsApp 是如何解决这个问题呢? 解决方案在这里:
也就说你必须通过其他方式,比如线下,来确认你使用的公钥确实是对方的公钥。终究还是必须要回到这个朴素但本质的问题。至于 Telegram 默认服务端则是明文保存消息的,就算是主动开启加密实际也逃不过这个本质的问题。
可审计的意思是,能否让用户较容易的确认软件的行为确实如他们所说的那样运行的。
WhatsApp 是不开源的;Telegram 是客户端开源,服务端不开源;Signal 是宣称客户端和服务端开源。
显然是否开源已非重点。那么关于可审计,我们应该关注什么?我们应该关注两点:
关于第一点,我们可以使用网络抓包工具(比如 mitmproxy 或 Wireshark) 来观测软件的所有上传数据。
当然,容易观测也就意味着容易破解,所以从某种角度来说可以理解。
所以纸诞生了,针对上面提到的问题,纸的解决方案如下:
正如 Telegram 创始人所说的,之所以 Telegram 默认不开启端到端加密的原因是为了使用方便,而使用方便才能够更流行。而端到端加密哪里不方便呢?就是无法多端设备无缝同步,因为服务端只有加密数据,而密钥只存在本机设备,要想同步到其他设备,必须得先把密钥弄到其他设备上。那么 WhatsApp 等是如何做的呢?它们使用了苹果的 iCloud 和 Google Drive 来同步,这也是 Telegram 创始人批评它们的一个点。总之,大家只需要记住一点,只要密钥通过第三方传递了,那么可信性就值得怀疑了。而纸采用预共享密钥,你需要自己把密钥放到你的其他设备上,一般为面对面扫码。纸也不会读取通讯录来获取联系人关系,那么就意味着纸只能更为小众。
关于纸的更多细节,请查看博客的其他文章。