Home  >  Article  >  Backend Development  >  thinkphp微信开发:安全模式讯息加解密

thinkphp微信开发:安全模式讯息加解密

WBOY
WBOYOriginal
2016-06-13 12:27:49770browse

thinkphp微信开发:安全模式消息加解密

       使用thinkphp官方的WeChat包,使用不同模式可以成功,但是安全模式就是不行,现将分析解决结果做下记录。

 

                                                                                                                                                                                                                  TRight

分析问题:

          解密微信服务器消息老是不成功,下载下微信公众平台官方给出的解密文件和WechatCrypt.class.php进行比对发现也没有问题。用file_put_contents函数保存下解密后的文件进行分析。发现官方包解密的xml不是标准的xml格式,所以simplexml_load_string函数无法处理。

<span style="color: #008000;">/*</span><span style="color: #008000;">*     * 对密文进行解密     * @param  string $encrypt 密文     * @return string          明文     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">public</span> <span style="color: #0000ff;">function</span> decrypt(<span style="color: #800080;">$encrypt</span><span style="color: #000000;">){        </span><span style="color: #008000;">//</span><span style="color: #008000;">BASE64解码</span>        <span style="color: #800080;">$encrypt</span> = <span style="color: #008080;">base64_decode</span>(<span style="color: #800080;">$encrypt</span><span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">打开加密算法模块</span>        <span style="color: #800080;">$td</span> = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, ''<span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化加密算法模块</span>        mcrypt_generic_init(<span style="color: #800080;">$td</span>, <span style="color: #800080;">$this</span>->cyptKey, <span style="color: #008080;">substr</span>(<span style="color: #800080;">$this</span>->cyptKey, 0, 16<span style="color: #000000;">));        </span><span style="color: #008000;">//</span><span style="color: #008000;">执行解密</span>        <span style="color: #800080;">$decrypt</span> = mdecrypt_generic(<span style="color: #800080;">$td</span>, <span style="color: #800080;">$encrypt</span><span style="color: #000000;">);               </span><span style="color: #008000;">//</span><span style="color: #008000;">去除PKCS7补位</span>        <span style="color: #800080;">$decrypt</span> = self::PKCS7Decode(<span style="color: #800080;">$decrypt</span>, mcrypt_enc_get_key_size(<span style="color: #800080;">$td</span><span style="color: #000000;">));        </span><span style="color: #008000;">//</span><span style="color: #008000;">关闭加密算法模块</span>        mcrypt_generic_deinit(<span style="color: #800080;">$td</span><span style="color: #000000;">);        mcrypt_module_close(</span><span style="color: #800080;">$td</span><span style="color: #000000;">);        </span><span style="color: #0000ff;">if</span>(<span style="color: #008080;">strlen</span>(<span style="color: #800080;">$decrypt</span>) ){            <span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> \<span style="color: #0000ff;">Exception</span>("非法密文字符串!"<span style="color: #000000;">);        }        </span><span style="color: #008000;">//</span><span style="color: #008000;">去除随机字符串</span>        <span style="color: #800080;">$decrypt</span> = <span style="color: #008080;">substr</span>(<span style="color: #800080;">$decrypt</span>, 16<span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">获取网络字节序</span>        <span style="color: #800080;">$size</span> = <span style="color: #008080;">unpack</span>("N", <span style="color: #008080;">substr</span>(<span style="color: #800080;">$decrypt</span>, 0, 4<span style="color: #000000;">));        </span><span style="color: #800080;">$size</span> = <span style="color: #800080;">$size</span>[1<span style="color: #000000;">];        </span><span style="color: #008000;">//</span><span style="color: #008000;">APP_ID</span>        <span style="color: #800080;">$appid</span> = <span style="color: #008080;">substr</span>(<span style="color: #800080;">$decrypt</span>, <span style="color: #800080;">$size</span> + 4<span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">验证APP_ID</span>        <span style="color: #0000ff;">if</span>(<span style="color: #800080;">$appid</span> !== <span style="color: #800080;">$this</span>-><span style="color: #000000;">appId){            </span><span style="color: #0000ff;">throw</span> <span style="color: #0000ff;">new</span> \<span style="color: #0000ff;">Exception</span>("非法APP_ID!"<span style="color: #000000;">);        }                </span><span style="color: #008000;">//</span><span style="color: #008000;">明文内容</span>        <span style="color: #800080;">$text</span> = <span style="color: #008080;">substr</span>(<span style="color: #800080;">$decrypt</span>, 4, <span style="color: #800080;">$size</span><span style="color: #000000;">);        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$text</span><span style="color: #000000;">;    }    </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * PKCS7填充字符     * @param string  $text 被填充字符     * @param integer $size Block长度     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> PKCS7Encode(<span style="color: #800080;">$text</span>, <span style="color: #800080;">$size</span><span style="color: #000000;">){        </span><span style="color: #008000;">//</span><span style="color: #008000;">字符串长度</span>        <span style="color: #800080;">$str_size</span> = <span style="color: #008080;">strlen</span>(<span style="color: #800080;">$text</span><span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">填充长度</span>        <span style="color: #800080;">$pad_size</span> = <span style="color: #800080;">$size</span> - (<span style="color: #800080;">$str_size</span> % <span style="color: #800080;">$size</span><span style="color: #000000;">);        </span><span style="color: #800080;">$pad_size</span> = <span style="color: #800080;">$pad_size</span> ? : <span style="color: #800080;">$size</span><span style="color: #000000;">;                </span><span style="color: #008000;">//</span><span style="color: #008000;">填充的字符</span>        <span style="color: #800080;">$pad_chr</span> = <span style="color: #008080;">chr</span>(<span style="color: #800080;">$pad_size</span><span style="color: #000000;">);        </span><span style="color: #008000;">//</span><span style="color: #008000;">执行填充</span>        <span style="color: #800080;">$text</span> = <span style="color: #008080;">str_pad</span>(<span style="color: #800080;">$text</span>, <span style="color: #800080;">$str_size</span> + <span style="color: #800080;">$pad_size</span>, <span style="color: #800080;">$pad_chr</span>,<span style="color: #000000;"> STR_PAD_RIGHT);        </span><span style="color: #0000ff;">return</span> <span style="color: #800080;">$text</span><span style="color: #000000;">;    }    </span><span style="color: #008000;">/*</span><span style="color: #008000;">*     * 删除PKCS7填充的字符     * @param string  $text 已填充的字符     * @param integer $size Block长度     </span><span style="color: #008000;">*/</span>    <span style="color: #0000ff;">private</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">function</span> PKCS7Decode(<span style="color: #800080;">$text</span>, <span style="color: #800080;">$size</span><span style="color: #000000;">){        </span><span style="color: #008000;">//</span><span style="color: #008000;">获取补位字符</span>        <span style="color: #800080;">$pad_str</span> = <span style="color: #008080;">ord</span>(<span style="color: #008080;">substr</span>(<span style="color: #800080;">$text</span>, -1<span style="color: #000000;">));        </span><span style="color: #0000ff;">if</span> (<span style="color: #800080;">$pad_str</span> $pad_str > <span style="color: #800080;">$size</span><span style="color: #000000;">) {            </span><span style="color: #800080;">$pad_str</span>= 0<span style="color: #000000;">;        }             </span><span style="color: #0000ff;">return</span> <span style="color: #008080;">substr</span>(<span style="color: #800080;">$text</span>, 0, <span style="color: #008080;">strlen</span>(<span style="color: #800080;">$text</span>) - <span style="color: #800080;">$pad_str</span><span style="color: #000000;">);            }</span>

解决方法:

           输出的xml文件是这样的

<span style="color: #008080;">1</span> <span style="color: #0000ff;"><span style="color: #800000;">xml</span><span style="color: #0000ff;">></span><span style="color: #008080;">2</span> <span style="color: #0000ff;"><span style="color: #800000;">ToUserName</span><span style="color: #0000ff;">></span><span style="color: #0000ff;"><span style="color: #808080;">gh_249aeb986d99</span><span style="color: #0000ff;">]]></span><span style="color: #0000ff;"><span style="color: #800000;">\/ToUserName</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">3</span> <span style="color: #0000ff;"><span style="color: #800000;">FromUserName</span><span style="color: #0000ff;">></span><span style="color: #0000ff;"><span style="color: #808080;">oopVmxHZaeQkDPsRcbpwXKkH-J2Q</span><span style="color: #0000ff;">]]></span><span style="color: #0000ff;"><span style="color: #800000;">\/FromUserName</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">4</span> <span style="color: #0000ff;"><span style="color: #800000;">CreateTime</span><span style="color: #0000ff;">></span>1448944621<span style="color: #0000ff;"><span style="color: #800000;">\/CreateTime</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">5</span> <span style="color: #0000ff;"><span style="color: #800000;">MsgType</span><span style="color: #0000ff;">></span><span style="color: #0000ff;"><span style="color: #808080;">text</span><span style="color: #0000ff;">]]></span><span style="color: #0000ff;"><span style="color: #800000;">\/MsgType</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">6</span> <span style="color: #0000ff;"><span style="color: #800000;">Content</span><span style="color: #0000ff;">></span><span style="color: #0000ff;"><span style="color: #808080;">\u7ecf\u7406</span><span style="color: #0000ff;">]]></span><span style="color: #0000ff;"><span style="color: #800000;">\/Content</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">7</span> <span style="color: #0000ff;"><span style="color: #800000;">MsgId</span><span style="color: #0000ff;">></span>6223169761311044588<span style="color: #0000ff;"><span style="color: #800000;">\/MsgId</span><span style="color: #0000ff;">></span><span style="color: #000000;">\n</span><span style="color: #008080;">8</span> <span style="color: #0000ff;"><span style="color: #800000;">\/xml</span><span style="color: #0000ff;">></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span>

       所以需要进行处理才能让simplexml_load_string处理

在输出的明文内容后面加上

<span style="color: #008080;">1</span> <span style="color: #000000;">//明文内容</span><span style="color: #008080;">2</span> <span style="color: #000000;">        $text = substr($decrypt, 4, $size);</span><span style="color: #008080;">3</span> <span style="color: #000000;">//去掉多余的内容</span><span style="color: #008080;">4</span>         $text=str_replace('<span style="color: #0000ff;"><span style="color: #800000;">\/','', $text</span><span style="color: #ff0000;">);      </span><span style="color: #008080;">5</span> <span style="color: #ff0000;">        $text</span><span style="color: #0000ff;">=str_replace('>\n','>', </span><span style="color: #ff0000;">$text);</span><span style="color: #008080;">6</span> <span style="color: #ff0000;">        return $text;</span></span>

 

 

安全模式就能正常使用了。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn