微信接入探秘(三)——加密消息的处理
来源:互联网 发布:网络攻击与防范 编辑:程序博客网 时间:2024/06/01 09:45
本文出处:http://blog.csdn.net/chaijunkun/article/details/53435972,转载请注明。由于本人不定期会整理相关博文,会对相应内容作出完善。因此强烈建议在原始出处查看此文
在上一篇博文中,介绍了被动回调接口的抽象数据层次,并实现了一个高效的实体与XML互转的基础功能。细心的开发者在初次修改公众号的基本配置时会发现一个名为“消息加解密方式”的选项。展开后可供选择的值为:“明文模式”(默认)、“兼容模式”和“安全模式(推荐)”。那么这个安全模式又是什么呢?如何适配安全模式呢?带着这些问题,来进入微信接入的第三次探秘之旅。
本专栏代码可在本人的CSDN代码库中下载,项目地址为:https://code.csdn.net/chaijunkun/wechat-common
可恶的流量劫持
在文章的一开始,先给大家看两幅处于正常使用中的手机屏幕截图:
在屏幕的右下角你会看到都有个绿色的水球显示,这与要显示的画面格格不入,很明显不是设计者为之。点开水球,显示的是当前通讯套餐中剩余的流量详情。
经过多方查证,它来自于北京联通。运营商强制将自己的代码注入到了当前显示的页面当中。也就是说,ISP在没经过用户同意的前提下,拦截了我们访问的内容,经过篡改后再返回给我们。例子中仅仅是流量提醒,有一些小规模的ISP甚至过分到直接私自插入广告。面对运营商级别的不法侵害,只有技术升级,采取一定的加密手段才能防止数据被非法篡改,其中HTTPS就是很好的方式。这也是为什么淘宝、京东等公司在全站实现HTTPS,
中间人监听
从家庭局域网络到Internet再到IDC机房内网,我们的数据链路充满了转发的过程。我们的数据在经过任何一台设备的转发时都有可能被其持久化保存起来。你的办公内网一定安全吗?潜伏在你身边的黑客,通过设置局域网内某个网卡为混杂模式(Promiscuous Mode)可以将局域网中的所有数据都接收一份。可能你并不能发现什么,然而你的私有数据已经被别人窃取。
使用安全模式保护用户隐私
微信的被动回调接口提供了一套基于消息加密的防范措施,来抵御这些我们面临的众多安全威胁。这里请注意,如果你提供的回调地址是https协议的,那么开启明文模式即可,因为整个传输链路层对你来说已经是安全的了。
安全模式的回调数据格式
当启用安全模式之后,被动回调接口接收到的消息就产生了很大的变化,形式如下所示:
<xml> <ToUserName><![CDATA[gh_38a2de904e09]]></ToUserName> <Encrypt><![CDATA[i7b8ccNA9OWDhau/F26aUWKFJ6Jd0imsDQIFPSdSfAg8mHT7rL0kIWSVpcqf6/dVSoOQOQK4T/CS3w96j4k3qcg89M6xn2RGZBs+9JkrsdRig5yhcia1B59akWb1t9QdutXqnl4edAqtXEh8SIs+N2HkOTTVldtOUHpdwLqRYuC4F6ejUoXui4xKuc3oyODR9edfL+xzZ7JfMJ1KUNF/YBJMj/Ba9y/CLLYmdFYOtCMH7tMUz8h+S0XKkHKN6r0ELLCIZJ9+PPlHZcfSGhwMLUeRF1nMIjXGEKHkI0uMcruh7wD96lMU/RFgJDjAk26xbmUYfa3l+34p+txw4R8iD3Q58S8Yekiy3lUsbk+C6eDeefGs1ck23BQ8xWU3AReWH2dEsY6SYIkb3ANeyJmcoIKZfpc/31njp0KcHAxL1Lk=]]></Encrypt></xml>
可以看出,明文部分保留了该消息的公众号原始ID:gh_38a2de904e09,其余部分均为加密文本(这种结构可以使得同一个后台系统,接入多个公众号,再利用每个公众号的设置进行分别解密)。由于加密结构在官方文档(http://qydev.weixin.qq.com/wiki/index.php?title=加解密库下载与返回码)中并没有明确的阐述,这里就给大家详细地说明一下。
如果读者以前开发过网络协议应该很容易理解这个结构,典型的不定长消息。一定会有一个标识来指明不定长区域的长度,读取时以该值为准,在定长数据之后读取若干字节。在结构的开头,有16字节随机数,该部分数据无实际意义,可用于后续返回加密消息时作为随机数的填充数据。
安全模式的签名验证方法
微信的被动回调接口实际上是一个HTTP POST请求,我们都知道HTTP请求分为请求头和请求体。微信巧妙地将加密的XML数据放在了请求体,将验证签名时使用的参数放入了请求头。
POST /cgi-bin/wxpush? msg_signature=477715d11cdb4164915debcba66cb864d751f3e6×tamp=1409659813&nonce=1372623149 HTTP/1.1Host: qy.weixin.qq.comContent-Length: 613<xml> <ToUserName><![CDATA[wx5823bf96d3bd56c7]]></ToUserName> <Encrypt><![CDATA[RypEvHKD8QQKFhvQ6QleEB4J58tiPdvo+rtK1I9qca6aM/wvqnLSV5zEPeusUiX5L5X/0lWfrf0QADHHhGd3QczcdCUpj911L3vg3W/sYYvuJTs3TUUkSUXxaccAS0qhxchrRYt66wiSpGLYL42aM6A8dTT+6k4aSknmPj48kzJs8qLjvd4Xgpue06DOdnLxAUHzM6+kDZ+HMZfJYuR+LtwGc2hgf5gsijff0ekUNXZiqATP7PF5mZxZ3Izoun1s4zG4LUMnvw2r+KqCKIw+3IQH03v+BCA9nMELNqbSf6tiWSrXJB3LAVGUcallcrw8V2t9EL4EhzJWrQUax5wLVMNS0+rUPA3k22Ncx4XXZS9o0MBH27Bo6BpNelZpS+/uh9KsNlY6bHCmJU9p8g7m3fVKn28H3KDYA5Pl/T8Z1ptDAVe0lXdQ2YoyyH2uyPIGHBZZIs2pDBS8R07+qN+E7Q==]]></Encrypt></xml>
签名生成的过程
通过上述计算,现在得出了当前加密消息的签名calculated_sign,然后从请求头中获取参数msg_signature,如果calculated_sign和msg_signature相同,则说明消息没有被篡改过。这种签名策略利用的数学难题有:
1. SHA1摘要算法对全部数据进行了计算,有任何改动最终的摘要都会发生变化;
2. Token是事先设置好的,在传输过程中并不包含,无从破解;
3. 时间戳和随机字符的引入,使得即便明文相同,每一次加密密文都有不同,给破解AES加密增加难度
签名验证成功之后就可以放心地使用解密后的明文了。明文的格式和之前文章中介绍的格式一致,因此解密后的业务处理逻辑可以复用。
作为安全模式的应答,返回的XML格式也应该是加密的,整个加密过程与解密过程方向相反,这里就不再赘述了。
- 微信接入探秘(三)——加密消息的处理
- 微信接入探秘(二)——懒人的OXM之路
- 微信接入探秘(二)——懒人的OXM之路
- 微信接入探秘(一)——从零认识微信接口
- 微信接入探秘(一)——从零认识微信接口
- 微信接入探秘(一)——从零认识微信接口
- 微信接入探秘(四)——万事俱备,只欠架构(回调篇)
- 微信接入探秘(五)——万事俱备,只欠架构(API篇)
- 微信sdk应用消息的接入(android)
- 微信公众号开发(一)——开发模式接入,消息的接收与响应
- 亲历H5移动端游戏微信支付接入及那些坑(三)——支付接入
- 最简单的PHP接入微信消息事件
- 用spring搭建微信公众号开发者模式下服务器处理用户消息的加密传输构架(java)
- Unity接入微信SDK——iOS(接入微信SDK)
- 微信公众号从头开发(接入与消息)
- Android消息处理探秘
- Android消息处理探秘
- 微信支付接入流程——刷卡支付接入
- thinkphp 通过“命令模式” 定义计划任务
- iOS-SVN无法上传静态库(.a)解决方案
- iOS:Swift自定义print
- cgo的一些经验
- 接口获取页面url参数
- 微信接入探秘(三)——加密消息的处理
- Spark/scala 写数据到Mysql数据库方法二
- android shape 资源的学习笔记
- 事件处理---屏蔽后退键
- sql查最新日期数据
- yalmip + lpsolve + matlab 求解混合整数线性规划问题(MIP/MILP)
- MyEclipse 2016 for Mac IDE中调出 Tomcat Servers 配置文件夹的方法
- git 放弃文件修改 和 版本回退
- android之四大组件