微信加密与安全通信流程分析

背景

​ 微信渐渐已经成为了大多数中国人日常会话的通讯工具。微信的通信安全,很大程度上保证了普通民众的数据安全,也因此显得十分重要。

​ 本文主要在其他对微信研究的基础上,进行了微信加密与验证的总结与分析。以便对微信的加密、验证安全有更加全面的接触与认识。

​ 本文主要从加密算法、验证流程分析、安全通信协议三方面进行介绍,主要对微信使用的mmtls进行了详细的分析。

加密算法

​ 我们首先将从最基本的加密算法出发,研究微信的加密方式。在通信中微信用到的加密算法主要用RSA公钥加密算法,AES随机密钥加密算法,这两个算法加密等级比较高,也因此难以破解。

RSA加密算法

​ RSA加密算法是目前一个普遍使用且比较安全的公钥加密算法。公钥加密也叫做非对称加密。它有着一对加密密钥(公钥)和解密密钥(私钥)。只有私钥才能解密。并且如果知道了其中一个,不能计算出另一个密钥。

​ RSA允许选择公钥的大小,公钥越长其安全性也越高。但是512位的密钥是被视作不安全的;1024位的密钥几乎是安全的。一般推荐使用1024位的密钥。

​ RSA的加密流程:

  • 首先,加密方产生明文字符串,获取CER认证公钥。
  • 加密机制通过Encoding指定不同的代码页,把字符串转换为不同页码对应的编码,为byte[]形式,再将byte[]字节流明文发送
  • 使用CER证书的公钥对byte[]字节流明文进行加密操作,以密文形式发送。

​ RSA解密流程:

  • 将公钥转换为PFX证书的私钥,使用PFX证书的私钥对byte[]密文进行解密,还原为byte[]明文字节流。

  • 使用加密时Encoding使用的代码页,把byte[]形式的明文转换成是字符串明文并发送。

    流程图示如下:

AES随机密钥加密算法

​ 微信的通信传输,全部基于AES随机密钥加密。AES是一个迭代的、对称密钥分组密码。它的密钥长度可以是128,192和256位。同时,使用128蚊分组加密和解密数据。

​ 与公钥加密相比,使用对称密钥加密速度比公钥快。因此在大多数的应用中,都是先使用如RSA加密算法来协商对称加密密钥,接着在之后的通信中使用对称加密来加密消息。微信也是如此。

​ 微信中使用的是129位AES随机密钥,它的强度是56位DES花奴强度的1000+倍。破解128位的AES密码需要的时间也很长,可以达到亿万年计。

​ 对称密钥加解密流程相似,每轮的AES加密循环均有如下四个步骤:

  • 字节替换:对数据的每一字节应用一个非线性变换
  • 行移位:对每一行的字节循环重新排序
  • 列混合:对矩阵的列应用一个线性变换
  • 轮密钥加:把轮密钥混合到中间数据

​ 不同的是最后一轮省略了列混合变换。

HKDF密钥扩展

​ HKDF的主要用来使用原始的密钥信息来派生出一个或者更多个可以达到密码学强度的密钥——将较短的密钥材料扩展成较长的密钥材料,过程中需要保证随机性。在微信通信协议mmtls中,微信使用了HKDF来扩展密钥。

​ HKDF主要包含两个基本模块,分别是

  • 提取 Extract:使用原始的密钥来派生出一个符合密码学强度的伪随机密钥;
  • 扩展 Expand:使用上一步的伪随机密钥,扩展出指定长度的密钥。

Extract

​ 他有三个输入分别是:

  • HAMC使用的Hash函数H,对应的输出长度是hashlen;
  • 原始密钥
  • 随机元salt,如果没有组默认是hashlen长度的0串

​ 输出:

  • hasklen长度的伪随机密钥

Expand

​ 他有四个输入分别是:

  • HAMC使用的hash函数H,H输出长度是hashlen
  • 第一步生成的随机密钥PRK
  • 另外的随机元info,可以为空
  • 期望生成的密钥长度L

​ 输出:

  • L长度的输出密钥OKM

流程及说明如下:

​ 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

​ Protocol Buffer用于结构化的数据描述、传输和存储。它是由谷歌公司开发的一种数据描述语言,基于二进制,因此比xml,json短小、高效。

​ 它的一个重要优点是可以保证同一消息报文新旧版本之间的兼容性。

mmtls

​ 为了保证安全隐私,以及快速的聊天体验,微信基于TLS1.3研发出了mmtls协议,并在微信中使用。

特点

​ mmtls的特点是:

  1. 安全。主要体现在防窃听,防篡改,防重放,防伪造。

  2. 低延迟、低资源消耗。数据在传输过程中不会增加明显的延迟;后台负载增加在可接受范围。

  3. 可用性。在一些极端情况下(如server负载过高),后台能够控制提供降级服务,且不被攻击者利用,进行降级攻击。

  4. 可扩展性。mmtls协议可扩展、可升级,方便添加安全强度更高的密码学组件,方便禁止过时的密码学组件。

    mmtls总体架构如下:

​ 进入mmtls内部,它包含三个子协议:Record协议、Handshake协议、Alert协议。他们的关系如下所示:

​ Handshake协议用于完成Client与Server的握手协商,协商出一个对称加密密钥Key以及其他密码材料,用于后续数据加密。Alert协议用于通知对端发生错误,希望对端关闭连接,目前mmtls为了避免server存在过多TCP Time-Wait状态,Alert消息只会server发送给client,由client主动关闭连接。而Record协议则使用对称加密密钥进行安全的通信。

​ 结合具体的使用场景,mmtls在TLS1.3的基础上主要做了以下几方面的工作:

  1. 轻量级。砍掉了客户端认证相关的内容;直接内置签名公钥,避免证书交换环节,减少验证时网络交换次数。

  2. 安全性。选用的基础密码组件均是TLS1.3推荐、安全性最高的密码组件;0-RTT防重放由proxy层和logic框架层协同控制。

  3. 高性能。使用0-RTT握手方式没有增加原有Client和Server的交互次数;和TLS1.3比,优化了握手方式和密钥扩展方式。

  4. 高可用性。服务器的过载保护,确保服务器能够在容灾模式下提供安全级别稍低的有损服务。

    下面我们将具体的分析mmtls协议:

Handshake协议——安全地协商出对称加密密钥

​ Handshake协议其实做的最主要的事情就是完成加密密钥的协商,即让通信双方安全地获得一致的对称密钥,以进行加密数据传输。在此基础上,还完成了一些优化工作,如复用session以减少握手时间。

​ mmtls结合微信的特点,在保证安全性和性能的前提下,只保留了三种密钥协商方式(1-RTT ECDHE, 1-RTT PSK, 0-RTT PSK),并做了一些优化。

​ 微信目前有两个数据传输信道:

  • 基于HTTP协议的短连接
  • 基于私有协议的长链接

​ 微信在其长链接中,建立好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认证密钥协商要好很多。

​ 下图为PSK密钥协商的流程示意:

​ 在mmtls中,为了节约公钥派发的时间,将verify_key直接内置在客户端,这样就避免证书链验证带来的时间消耗以及证书链传输带来的带宽消耗。

​ 上面的密钥协商方式都额外需要一个RTT去获取对称加密key。但是还存在着一种密钥协商方式可以在握手协商过程中安全地将业务数据传递给对端,即0-RTT密钥协商。

​ 在微信中,预先生成一对公私钥(static_svr_pub_key, static_svr_pri_key)并将static_svr_pub_key预置在Client中,那么Client可以在发起握手前就通过static_svr_pub_kecli_pub_key生成一个对称密钥SS(Static Secret),然后用SS加密第一个业务数据包(实际上是通过SS衍生的密钥对业务数据进行加密,后面详述),这样将SS加密的业务数据包和cli_pub_key一起传给Server,Server通过cli_pub_keystatic_server_private_key算出SS,解密业务数据包,这样就达到了0-RTT密钥协商的效果。

Record协议——使用对称加密密钥进行安全的通信

​ 经过上面的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不能直接作为对称加密密钥,而是需要经过扩展变换,得到六个对称加密参数。

  • Client Writer MAC Key:用于客户端计算消息认证码,及服务端验证;
  • Server Writer MAC Key:用于服务端计算消息验证码,及客户端验证;
  • Client Write Encryption Key:用作客户端加密,及服务端解密;
  • Server Write Encryption Key:用作服务端加密,及客户端解密;
  • Client Write IV:客户端加密时候的初始化向量;
  • Server Write IV:服务端加密时候的初始化向量。

​ 实际上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要求必须实现的算法。

流程分析

登录认证分析

​ 实际上微信对登陆过程分了两种情况,分别是设备第一次登陆和设备之后的登陆。

​ 若某台设备首次登陆微信,那么微信就会在登陆过程中向设备返回一些配置文件。之后除非卸载微信,那么这些配置文件就不需要更改。

  • 首先客户端向服务器发送登陆请求报文。报文中包含了账户、密码、MD5加密信息、随机AES密钥,并使用RSA公钥加密登录包,发送给服务器。
  • 服务器收到登录包后,使用RSA私钥解密,获取包中信息,对用户的账户密码进行核验。将最后生成的验证包使用AES密钥加密发送给客户端。
  • 客户端收到验证包,使用AES解密后获取验证信息,之后的通信就使用AES进行加密了。
  • 登录验证成功后,客户端还会基于HTTP协议向服务器获取系统配置信息。
  • 在整个登录过程,数据都是按照Protocol Buffer进行构造解析。

通信交互分析

​ 对于微信的会话加密,由于登录过程中已经使用了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)

微信加密与登录验证分析相关推荐

  1. 商软B v5.4.1的登录验证分析

    B的验证方式:登录时联网验证vip,验证通过即可享受下载加速.在线解压.自动备份等vip功能.在登录时,B会首先提取本地缓存文件中的vip信息写入内存,之后联网验证账号.本地缓存的vip信息,返回服务 ...

  2. 微信扫码登录验证PHP代码(不用开放平台)

    public function wxqrcheckAction(){if(g('ajaxchk')!=''){ //前端页面显示二维码并AJAX定时检查已否已扫码验证if(isset($_SESSIO ...

  3. 易班APP登录密码加密、sig逆向分析

    1.最近闲来无事,听说有一个易班app登录好练手,就去试了一下看看. 先抓个包看看 然后使用了腾讯的壳,脱一下,我这边用的是BlackDex64. 脱完壳之后导出来直接导出来拖到jadx,就是现在这个 ...

  4. 微信公众号登录密码参数加密详解

    微信公众号登录密码pwd参数加密详解 前言 此参数的加密没有任何难度,适合小白练手学习. 网址:https://mp.weixin.qq.com/ 一.打开浏览器开始抓包 输入错误的账号密码,登录.然 ...

  5. 微信小程序登录 + 基于token的身份验证

    官方时序图如下: https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html 图里其实说的很清 ...

  6. 常见登录验证方式分析以及流程图示例

    常见的登录验证方式 账号/邮箱/手机号 + 验证码 + 密码 邮箱 + 动态邮箱验证码 手机号 + 动态短信/语音验证码 第三方授权登录,微信扫码登录等 OCR人脸识别校验登录(移动端可用方案,暂未分 ...

  7. qt调用mysql加密接口_Qt实现客户端/服务器端登录验证|数据传输使用md5加密 | 学步园...

    要完成两个模块:客户端和服务器端.即实现通过客户端向远程服务器段发送数据来验证,以此来实现简单的认证功能.同时,客户端在向服务器段发送的数据通过md5加密后再传送. 开发环境与工具 开发操作系统:Wi ...

  8. 微信小程序python token验证_微信小程序登录对接Django后端实现JWT方式验证登录

    点击授权按钮后可以显示部分资料和头像,点击修改资料可以修改部分资料. 1.使用微信小程序登录和获取用户信息Api接口 2.把Api获取的用户资料和code发送给django后端 3.通过微信接口把co ...

  9. 微信小程序登录页验证与页面跳转

    微信小程序登录页实现验证登录和页面跳转 利用js实现验证登录和页面跳转,开发工具是微信开发者工具. wxml部分 登录页面的代码,需要再创建一个主页. <view class="wel ...

最新文章

  1. ThinkPHP5表单令牌+表单数据验证验证规则
  2. mysql查看比较大的数据表_mysql 如何查看哪些表数据量比较大
  3. 学Linux从编译命令开始——arm-linux-gcc常用参数讲解
  4. macOS的控制台Console.app
  5. 【斗医】【3】Web应用开发20天
  6. 题目1022:游船出租(结构体使用)
  7. 主节点数量_你知道电气主接线常见接线方式吗?建议收藏共同学习
  8. 3月5日 灭点身高测量,点线齐次坐标表示,交点计算,无穷远处的点线,平移旋转的理解
  9. 解决Tomcat中文乱码
  10. 如何建立远程桌面连接?
  11. mybatis/mybatis plus lambda会话缓存失效(1)
  12. docker三剑客之 Docker Machine Docker Compose Docker Swarm
  13. oracle ora 3136,oracle中ORA-3136,ORA-609
  14. 零死角玩转stm32中级篇2-IIC总线
  15. samba服务器的安装
  16. QGIS插件python开发环境配置和PyCharm配置调试环境
  17. java/php/net/python西石大快递代取系统设计
  18. Google Maps JavaScript API 使用
  19. quill富文本编辑器——修改默认图片、视频上传功能
  20. php 获取配置信息,PHP系统配置信息的获取

热门文章

  1. 第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息
  2. UI组件介绍(for设计师)
  3. NSString 和 UInt8 相互转换
  4. 百度地图获取数据库点的坐标,并定时刷新到页面上,功能一
  5. Debian9初始配置
  6. :爱情从来就没有愚人节
  7. 1+6t刷个lineage OS 20(Android13)
  8. 信号处理--sinc函数
  9. python图像拼接_python实现图像拼接
  10. Microsoft Word 标题编号变成黑块的解决方法