流水不争先,争的是滔滔不绝

为什么相同的消息微信每次加密后发送的内容都不一样?

即时通讯软件开发 云聊IM 2732℃

抓包分析微信的消息,发现发送同样的内容,抓取到的数据包内容都不相同。这到底是怎么回事呢?

显然,微信并不是每次发送消息都跟服务器端约定秘钥(如果那样,性能和流量恐怕大家都不能接受)。那每次加密内容都不一样到底是怎样实现的呢?

基本思路分为两个部分

1、秘钥交换。微信(之后称客户端)每次与微信服务器(之后称服务端)建立TCP长连接后,首先进行握手操作(handshake),这个过程类似https或ssl的秘钥交换过程。

2、秘钥加盐。在每次发送消息是,客户端向秘钥加“盐 ”,再将“盐”随着消息发往服务端。而这个“盐”,往往是消息协议中随每次消息发送变化的合法内容。

貌似这两条有点抽象,后边会有具体步骤说明。在此之前,需要了解一个序列号(seq)的概念。

一般一条消息的数据协议如下图所示。包括header和body两部分。

其中header中有一个seq的字段,表示消息序列号。客户端每向服务端发送一条消息,seq+1。因此seq是一个每次发送消息都会变化的量(当然seq用途远不止用于加密)。

了解了seq的概念,我们来看看加密过程。

  1. 1、客户端生成随机数R1
  2. 2、客户端使用ECC(或者RSA)非对称加密算法,用公钥将R1加密发给服务端
  3. 3、服务端使用ECC(或者RSA) 算法私钥解密数据,得到R1
  4. 4、服务端生成随机数R2,采用AES算法加密R2,秘钥为R1。并将加密后的R2发给客户端。
  5. 5、客户端采用AES算法,以R1为秘钥,解密得到R2.

至此,客户端和服务端均得到R1,R2

  1. 6、客户端发送数据。每条消息会生成一个seq(传输协议中的seq),将R1,R2,seq按照各端约定的方式混合,生成msgKey。 msgKey=mix(R1,R2,seq)
  2. 7、使用msgKey为秘钥,用AES算法加密消息,并发送。
  3. 8、服务端收到消息,混合R1,R2,seq生成msgKey。完成解密。

这个过程,确保了每条消息加密秘钥都不一致。

此外,所采用的ECC(或RSA)的秘钥,跟客户端版本(clientVersion,参看消息协议图中header部分)关联。不同的客户端版本可以采用不同的秘钥。

最后,微信到底是不是这么做的呢?我不知道,我猜它是这么做的。

转自:微信公众号【普通程序员】

作者:封宇

版权声明:部分文章、图片等内容为用户发布或互联网整理而来,仅供学习参考。如有侵犯您的版权,请联系我们,将立刻删除。
点击这里给我发消息