# 消息加密说明

# 概述

服务器在推送消息给开发者时,会对消息内容做AES加密,以JSON格式POST到开发者设置的回调URL上。

本章节即是对加解密方法的说明。

阅读本章节前,需要了解以下术语:

  • signature: 消息签名,用于验证请求是否来自企业微信(防止攻击者伪造)。
  • EncodingAESKey:用于消息体的加密,长度固定为43个字符,从a-z, A-Z, 0-9共62个字符中选取,是AESKey的Base64编码。解码后即为32字节长的AESKey AESKey=Base64_Decode(EncodingAESKey + “=”)
  • AESKey:AES算法的密钥,长度为32字节。
  • AES采用CBC模式,数据采用PKCS#7填充至32字节的倍数;IV初始向量大小为16字节,取AESKey前16字节,详见:http://tools.ietf.org/html/rfc2315
  • msg:为消息体明文,格式为JSON
  • msg_encrypt:明文消息msg加密处理后的Base64编码。

# 消息体签名校验

为了让开发者确认调用来自API服务器,服务器在回调给接收消息url时会带上消息签名,以参数signature标识,开发者需要验证此参数的正确性后再解密。

验证步骤如下:

1. 计算签名

dev_signature=sha1(sort(token、timestamp、nonce、msg_encrypt))

sort的含义是将参数值按照字母字典排序,然后从小到大拼接成一个字符串

sha1处理结果要编码为可见字符,编码的方式是把每字节散列值打印为%02x(即16进制,C printf语法)格式,全部小写

2. 比较 dev_signaturesignature 是否相等,相等则表示验证通过

# 明文msg的加密过程

1. 拼接明文字符串

rand_msg = random(16B) + msg_len(4B) + msg + receiveid

明文字符串由16个字节的随机字符串、4个字节的msg长度、明文msg和receiveid拼接组成。其中msg_len为msg的字节数,网络字节序(即 BIG_ENDIAN 字节序);receiveid 为开发者的appId。

2. 对明文字符串加密并Base64编码

msg_encrypt = Base64_Encode(AES_Encrypt(rand_msg))

将明文字符串AESKey加密后,再进行Base64编码,即获得密文msg_encrypt。

# 密文解密得到msg的过程

1. 对密文BASE64解码

aes_msg=Base64_Decode(msg_encrypt)

2. 使用AESKey做AES-256-CBC解密

rand_msg=AES_Decrypt(aes_msg)

3. 去掉rand_msg头部的16个随机字节和4个字节的msg_len,截取msg_len长度的部分即为msg,剩下的为尾部的receiveid

4. 验证解密后的receiveid、msg_len。

# 使用已有库

解码库请参考企业微信加解密方案说明 (opens new window)

注意企业微信默认推送的消息格式为XML,本API推送的消息格式为JSON。