微信渐渐已经成为了大多数中国人日常会话的通讯工具。微信的通信安全,很大程度上保证了普通民众的数据安全,也因此显得十分重要。
本文主要在其他对微信研究的基础上,进行了微信加密与验证的总结与分析。以便对微信的加密、验证安全有更加全面的接触与认识。
本文主要从加密算法、验证流程分析、安全通信协议三方面进行介绍,主要对微信使用的mmtls进行了详细的分析。
我们首先将从最基本的加密算法出发,研究微信的加密方式。在通信中微信用到的加密算法主要用RSA公钥加密算法,AES随机密钥加密算法,这两个算法加密等级比较高,也因此难以破解。
RSA加密算法是目前一个普遍使用且比较安全的公钥加密算法。公钥加密也叫做非对称加密。它有着一对加密密钥(公钥)和解密密钥(私钥)。只有私钥才能解密。并且如果知道了其中一个,不能计算出另一个密钥。
RSA允许选择公钥的大小,公钥越长其安全性也越高。但是512位的密钥是被视作不安全的;1024位的密钥几乎是安全的。一般推荐使用1024位的密钥。
RSA的加密流程:
RSA解密流程:
将公钥转换为PFX证书的私钥,使用PFX证书的私钥对byte[]密文进行解密,还原为byte[]明文字节流。
使用加密时Encoding使用的代码页,把byte[]形式的明文转换成是字符串明文并发送。
流程图示如下:
微信的通信传输,全部基于AES随机密钥加密。AES是一个迭代的、对称密钥分组密码。它的密钥长度可以是128,192和256位。同时,使用128蚊分组加密和解密数据。
与公钥加密相比,使用对称密钥加密速度比公钥快。因此在大多数的应用中,都是先使用如RSA加密算法来协商对称加密密钥,接着在之后的通信中使用对称加密来加密消息。微信也是如此。
微信中使用的是129位AES随机密钥,它的强度是56位DES花奴强度的1000+倍。破解128位的AES密码需要的时间也很长,可以达到亿万年计。
对称密钥加解密流程相似,每轮的AES加密循环均有如下四个步骤:
不同的是最后一轮省略了列混合变换。
HKDF的主要用来使用原始的密钥信息来派生出一个或者更多个可以达到密码学强度的密钥——将较短的密钥材料扩展成较长的密钥材料,过程中需要保证随机性。在微信通信协议mmtls中,微信使用了HKDF来扩展密钥。
HKDF主要包含两个基本模块,分别是
他有三个输入分别是:
输出:
他有四个输入分别是:
输出:
流程及说明如下:
T(0) = 空
T(1) = HMAC-Hash(PRK, T(0) || info || 0x01)
T(2) = HMAC-Hash(PRK, T(1) || info || 0x02)
T(3) = HMAC-Hash(PRK, T(2) || info || 0x03)
…
微信通信系统选用了Protocl Buffer作为通信协议。同时微信也自研出了mmtls作为他们的通信协议。我们将对这两个协议进行介绍。
Protocol Buffer用于结构化的数据描述、传输和存储。它是由谷歌公司开发的一种数据描述语言,基于二进制,因此比xml,json短小、高效。
它的一个重要优点是可以保证同一消息报文新旧版本之间的兼容性。
为了保证安全隐私,以及快速的聊天体验,微信基于TLS1.3研发出了mmtls协议,并在微信中使用。
mmtls的特点是:
安全。主要体现在防窃听,防篡改,防重放,防伪造。
低延迟、低资源消耗。数据在传输过程中不会增加明显的延迟;后台负载增加在可接受范围。
可用性。在一些极端情况下(如server负载过高),后台能够控制提供降级服务,且不被攻击者利用,进行降级攻击。
可扩展性。mmtls协议可扩展、可升级,方便添加安全强度更高的密码学组件,方便禁止过时的密码学组件。
mmtls总体架构如下:
进入mmtls内部,它包含三个子协议:Record协议、Handshake协议、Alert协议。他们的关系如下所示:
Handshake协议用于完成Client与Server的握手协商,协商出一个对称加密密钥Key以及其他密码材料,用于后续数据加密。Alert协议用于通知对端发生错误,希望对端关闭连接,目前mmtls为了避免server存在过多TCP Time-Wait状态,Alert消息只会server发送给client,由client主动关闭连接。而Record协议则使用对称加密密钥进行安全的通信。
结合具体的使用场景,mmtls在TLS1.3的基础上主要做了以下几方面的工作:
轻量级。砍掉了客户端认证相关的内容;直接内置签名公钥,避免证书交换环节,减少验证时网络交换次数。
安全性。选用的基础密码组件均是TLS1.3推荐、安全性最高的密码组件;0-RTT防重放由proxy层和logic框架层协同控制。
高性能。使用0-RTT握手方式没有增加原有Client和Server的交互次数;和TLS1.3比,优化了握手方式和密钥扩展方式。
高可用性。服务器的过载保护,确保服务器能够在容灾模式下提供安全级别稍低的有损服务。
下面我们将具体的分析mmtls协议:
Handshake协议其实做的最主要的事情就是完成加密密钥的协商,即让通信双方安全地获得一致的对称密钥,以进行加密数据传输。在此基础上,还完成了一些优化工作,如复用session以减少握手时间。
mmtls结合微信的特点,在保证安全性和性能的前提下,只保留了三种密钥协商方式(1-RTT ECDHE, 1-RTT PSK, 0-RTT PSK),并做了一些优化。
微信目前有两个数据传输信道:
微信在其长链接中,建立好TCP连接之后,会先发一个nooping包,验证长链接的连通性。因此长链接在建立时候第一个数据报不会发送数据,因此采用1-RTT的握手方式,用第一个握手包取代nooping包。因此长链接之下使用1-RTT ECDHE和1-RTT PSK这两种密钥协商方式。
为了防止中间人攻击,在mmtls中采用ECDSA的数字签名算法。在进行密钥协商时候,双方密钥协商时,再分别运行签名算法对自己发出的公钥进行签名。收到信息后,首先验证签名,如果签名正确,则继续进行密钥协商。攻击者没有办法阻止别人获取公钥,除非完全掐断发送方的通信。这样一来,中间人攻击就不存在了。
为了优化通信过程,在微信中,mmtls就是只对Server做认证,不对Client做认证,因为微信客户端发布出去后,任何人都可以获得,只要能够保证客户端程序本身的完整性,就相当于保证了客户端程序是由官方发布的,而客户端程序本身的完整性不是mmtls协议保护的范畴。
接着进行PSK密钥协商,Client将PSK的ticket{key}
部分发送给Server,由于只有Server才知道ticket_key
,因此key是不会被窃听的。Server拿到ticket后,使用ticket_key
解密得到key,然后Server用基于协商得到的密钥key,对协商数据计算消息认证码来认证,这样就完成了PSK认证密钥协商。PSK认证密钥协商使用的都是对称算法,性能上比ECDH认证密钥协商要好很多。
在mmtls中,为了节约公钥派发的时间,将verify_key
直接内置在客户端,这样就避免证书链验证带来的时间消耗以及证书链传输带来的带宽消耗。
上面的密钥协商方式都额外需要一个RTT去获取对称加密key。但是还存在着一种密钥协商方式可以在握手协商过程中安全地将业务数据传递给对端,即0-RTT密钥协商。
在微信中,预先生成一对公私钥(static_svr_pub_key, static_svr_pri_key)
并将static_svr_pub_key
预置在Client中,那么Client可以在发起握手前就通过static_svr_pub_ke
和cli_pub_key
生成一个对称密钥SS(Static Secret)
,然后用SS加密第一个业务数据包(实际上是通过SS衍生的密钥对业务数据进行加密,后面详述),这样将SS加密的业务数据包和cli_pub_key
一起传给Server,Server通过cli_pub_key
和static_server_private_key
算出SS,解密业务数据包,这样就达到了0-RTT密钥协商的效果。
经过上面的Handshake过程,此时Client和Server已经协商出了一致的对称加密密钥pre_master_key
,那么接下来就可以直接用这个pre_master_key
作为密钥,选择一种对称加密算法(如常用的AES-CBC)加密业务数据,将密文发送给Server。实际上如果真的按这个过程进行加密通信是有很多安全漏洞。
mmtls经过综合考虑,选择了使用AES-GCM这种AEAD类算法,作为协议的认证加密组件,而且AES-GCM也是TLS1.3要求必须实现的算法。
AES算法的初始化向量IV一旦用错会有安全漏洞,因此handshake协议协商得到的pre_master_secret不能直接作为对称加密密钥,而是需要经过扩展变换,得到六个对称加密参数。
实际上MAC Key和Encryption Key只需要一个就可以了。握手生成的pre_master_secret只有48字节,mmtls使用HKDF做密钥扩展生成上述参数。
为了防范重放攻击,微信为每一个业务包编一个递增的sequence number。mmtls的做法是将sequence number作为构造AES-GCM算法参数nonce的一部分,利用AES-GCM的算法特性,只要AES-GCM认证解密成功就可以确保sequence number符合预期。
为了保证数据来源的可靠性(认证),mmtls经过综合考虑,选择了使用AES-GCM这种AEAD类算法,作为协议的认证加密组件,而且AES-GCM也是TLS1.3要求必须实现的算法。
实际上微信对登陆过程分了两种情况,分别是设备第一次登陆和设备之后的登陆。
若某台设备首次登陆微信,那么微信就会在登陆过程中向设备返回一些配置文件。之后除非卸载微信,那么这些配置文件就不需要更改。
对于微信的会话加密,由于登录过程中已经使用了AES密钥,之后的通信都是基于此AES密钥的。但是在通信过程中,服务器会随机生成会话密钥,且会话密钥的生命周期不长,会时长改变。之后的通信都是在会话密钥加密下进行的。
这里的具体交互协议则可以参考上面所介绍的mmtls协议。
由上述分析可见,为了保证安全性,一方面,微信使用了RSA与AES等安全的加密方式,另一方面,也根据业务需求制定了适合微信的通信协议。以mmtls为例,他在TLS基础上做了一定的删减以及完善,从而达到了安全的密钥协商以及加密工作。同时为了减少通信量,微信也使用了HKDF密钥拓展,以及将服务端的某些密钥信息内嵌在程序中。微信中所使用的通信协议设计,对于我们也有着很大的参考意义。
[1]瞿晓海,薛质.微信加密通信原理分析[J].信息安全与技术,2014,5(01):13-16.
[2]万园春,顾旸铖,邱卫东.微信交互协议和加密模式研究[J].微型电脑应用,2015,31(02):31-34.
[3]基于TLS1.3的微信安全通信协议mmtls介绍 https://mp.weixin.qq.com/s/tvngTp6NoTZ15Yc206v8fQ;
[4] RFC5869: HMAC-based Extract-and-Expand Key Derivation Function (HKDF)