端对端加密通讯(end-to-end encrypted instant messaging)

最近看了我校BBS的兴衰史,感觉十年后的今天,言论控制却是越来越严格。如今,人们日常使用的微信、QQ的即时通讯工具,也未承诺用户数据的安全(可以不负责任地揣测某局是可以实时监控网民的聊天内容的)。嘛,小市民是没有什么担忧啦。这里用交流与学习的态度,介绍端对端加密的通讯是如何实现的。

基础知识

根本没学过密码学的我保证本节不都是胡说八道

所谓端对端,我粗浅的理解就是,两人之间的对话,在传播过程中是全程加密的状态,并且没有中间人(包括服务器本身)可以简单地破译传输的密文。其中,最关键的问题就是,两人之间如何商定加密和解密的协议。发个email告诉对方规则不就好了?那规则的传输(email、小纸条)是否是安全的呢?

由此引出两种加密方式:对称密钥加密symmetric)和公钥加密asymmetric)方式。

对称加密,是最直观的办法,对话双方拥有相同的密钥(shared secret),利用这个密钥加密要传输的数据,以及解密传达的密文。大致可以表示为以下过程:

$ \mathrm{msg_{encrypted}} = f(\mathrm{msg}, key) $

$ \mathrm{msg} = g(\mathrm{msg_{encrypted}}, key) $

这里,算法(f, g)必须保证相同的密钥(key)既能加密也能解密。这种方式,存在的缺点就是上文提到的“双方必须提前商定好规则”,即相同的密钥。而通常来说,传输环境无法保证密钥的安全性。优点则是本地加密速度较快,适用于传输大量数据。拿传纸条来说明的话,就是两人如果在下课的时候私下商定好加密方式,上课的时候纸条上的密文就不用担心(一定程度上)被中间人窃听/篡改。

公钥加密方式,则是将一部分密钥信息公开,让对方用于加密,然后传输密文回复,下图可以说明其中的一次信息传输。这里的Alice有两个密钥:公钥(public key)和私钥(private key),然后通过不安全的方式将公钥传给Bob。之后,Bob把计划发给Alice的原文用Alice的公钥加密,传给Alice,而Alice可以用她自己的私钥解密。在这种通讯中,双方的公钥都是不安全的,但是因为其中包含私钥的信息(它们是成对的密钥),可以在各自保留秘密的情况下进行加密通讯。这类算法中很重要的就是,用公钥破译私钥需要极大的计算量,保证公钥的泄露不会影响私钥的安全。其中,很常用的RSA算法,就是利用了大数因式分解的计算复杂度,具体过程可以参考wiki链接

Diffie–Hellman密钥交换则解决了密钥交换的安全问题。双方在同样的规则下各产生一对密钥,其中公钥包含着私钥的信息,但是只通过公钥是无法很难解析私钥的。而这种算法的奇妙之处在于,双方通过交换公钥之后,跟各自的私钥混合,可以产生相同的密钥,于是就可以用这个共有密钥进行前文提到的对称加密了。

然而,这样就万无一失了吗?上述两种方法,都无法解决中间人攻击(Man-in-the-middle attack)。试想一下,Alice和Bob中间有一个坏蛋,同时扮演着对方的角色,使用相同的加密规则跟两人进行交流,由于缺乏验证机制,Alice和Bob无法判断与自己对话的是否本人。于是,引入数字签名,通过例如加密证书之类的东西,验证收到的公钥是否安全无误。现在,逐渐成为主流的https站点,就是利用了SSL/TSL进行安全传输的例子,它可以保证客户端和服务端的通讯不受中间人干扰。

聊天网站/软件

我们来看看现在市面上的即时通讯(IM)软件都用了什么加密手段:列表传送门。可以看到,它们分为两类,client-to-client和client-to-server,即:服务器是否解密你的消息。前者,即本文要实现的端对端加密,服务器只负责传递公钥和密文之类的数据;而后者大概可以理解为服务器就是上文提到的“中间人”,负责消息的传递,这里的加密主要是防止传输过程中被窃取(微信、QQ大致属于这类)。

但是,人们凭什么相信这些通讯软件不会窃取我们的私钥?开源是一种很好的办法,让人们监督它的具体实现过程。大家可以去研读TelegramSignal的源码,应该会受益匪浅=-=

简单实现

这里我也小试牛刀,看看小作坊的聊天网站能不能实现。因为是小作坊,就暂时不提供身份验证的方法,简单利用Diffie Hellman方法,交换生成密钥,hash之后作为AES加密的密码。服务器本身只进行用户的管理,公钥及密文的分发工作。项目地址:sechat,取secret chat/secure chat之意(不要笑)。

目前,只有一个聊天室,用户打开网站之后,设置昵称即可开始聊天。可以选择给当前在线的某个人发送私信,也可以给所有人发公开消息。。。(因为用户大概不会很多,单独的聊天室尚未开发)

风格嘛,就是terminal的画风(gruvbox配色,后续会提供用户选项,估计得学一下sass =-=):

感兴趣的话,点击:http://zengwh.com/chat 作测试吧!

因为没有开启https,安全级别还是很低的,大家带着看demo的心态就好。

如果有什么建议和idea,请不要犹豫,留下评论吧。