# 消息加密说明
# 概述
服务器在推送消息给开发者时,会对消息内容做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_signature
和 signature
是否相等,相等则表示验证通过
# 明文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。