zoukankan      html  css  js  c++  java
  • 【PHP7.1】使用OpenSSL来代替Mcrypt加解密【原创】


    概要:

    今天在使用微信开放平台对接一个内容管理系统的时候,在绑定公众号的时候一直失败


    原因:

    调试的时候发现,直接原因是因为开放平台里面填写的授权事件(该授权事件每十分钟会通送一次事件来更新ticket),即:


    这个地方填写的url,调试发现,这个URL没错,微信也有每10分钟推送过来,但是到最后一直接收不到ticket,看代码发现是因为解密微信过来的数据的时候报错了:

    <?php
    
    function aes_decode($message, $encodingaeskey = '', $appid = '') {
    	$key = base64_decode($encodingaeskey . '=');
    
    	$ciphertext_dec = base64_decode($message);
    	$iv = substr($key, 0, 16);
    
    	$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
    	mcrypt_generic_init($module, $key, $iv);
    	$decrypted = mdecrypt_generic($module, $ciphertext_dec);
    	mcrypt_generic_deinit($module);
    	mcrypt_module_close($module);
    
    	$pad = ord(substr($decrypted, -1));
    	if ($pad < 1 || $pad > 32) {
    		$pad = 0;
    	}
    即这个地方,由于我的环境是PHP 7.1,查找资料发现PHP 7.1已经废弃了Mcrypt,所以这个代码里面的mcrypt_*都是无法运行的。


    解决:

    查找资料发现,可以通过OpenSSL来代替Mcrypt(前提是已经安装了OpenSSL扩展,不过一般都是默认安装的),所以上面的代码可以改为:

    <?php
    
    function aes_decode($message, $encodingaeskey = '', $appid = '') {
    	$key = base64_decode($encodingaeskey . '=');
    
    	$ciphertext_dec = base64_decode($message);
    	$iv = substr($key, 0, 16);
    
    	/* mcrypt对称解密代码在PHP7.1已经被抛弃了,所以使用下面的openssl来代替
    	$module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
    	mcrypt_generic_init($module, $key, $iv);
    	$decrypted = mdecrypt_generic($module, $ciphertext_dec);
    	mcrypt_generic_deinit($module);
    	mcrypt_module_close($module);
        */
        $decrypted = openssl_decrypt($ciphertext_dec, 'AES-256-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
    
    	$pad = ord(substr($decrypted, -1));
    	if ($pad < 1 || $pad > 32) {
    		$pad = 0;
    	}

    补充:

    上面的解密已经修改了,那么对应的Mcrypt加密也需要修改,如果不改的话会导致不能全网发布以及不能推送消息等事件

    加密的源代码如下:

    <?php
    function aes_encode($message, $encodingaeskey = '', $appid = '') {
        $key = base64_decode($encodingaeskey . '=');
        $text = random(16) . pack("N", strlen($message)) . $message . $appid;
        $iv = substr($key, 0, 16);
    
        $block_size = 32;
        $text_length = strlen($text);
        $amount_to_pad = $block_size - ($text_length % $block_size);
        if ($amount_to_pad == 0) {
            $amount_to_pad = $block_size;
        }
        $pad_chr = chr($amount_to_pad);
        $tmp = '';
        for ($index = 0; $index < $amount_to_pad; $index++) {
            $tmp .= $pad_chr;
        }
        $text = $text . $tmp;
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($module, $key, $iv);
        $encrypted = mcrypt_generic($module, $text);
        mcrypt_generic_deinit($module);
        mcrypt_module_close($module);
    
        $encrypt_msg = base64_encode($encrypted);
        return $encrypt_msg;
    }

    修改后的代码为:

    <?php
    function aes_encode($message, $encodingaeskey = '', $appid = '') {
        $key = base64_decode($encodingaeskey . '=');
        $text = random(16) . pack("N", strlen($message)) . $message . $appid;
        $iv = substr($key, 0, 16);
    
        $block_size = 32;
        $text_length = strlen($text);
        $amount_to_pad = $block_size - ($text_length % $block_size);
        if ($amount_to_pad == 0) {
            $amount_to_pad = $block_size;
        }
        $pad_chr = chr($amount_to_pad);
        $tmp = '';
        for ($index = 0; $index < $amount_to_pad; $index++) {
            $tmp .= $pad_chr;
        }
        $text = $text . $tmp;
        /* mcrypt对称加密代码在PHP7.1已经被抛弃了,所以使用下面的openssl来代替
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($module, $key, $iv);
        $encrypted = mcrypt_generic($module, $text);
        mcrypt_generic_deinit($module);
        mcrypt_module_close($module);
        */
    
        $encrypted = openssl_encrypt($text, 'AES-256-CBC', $key, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
        $encrypt_msg = base64_encode($encrypted);
        return $encrypt_msg;
    }

    凡是涉及到微信开发的流程,如果已经升级到PHP 7.1的话,那么很有必要需要检查一下是否是使用Mcrypt对称加解密的,微信开发文档中使用的demo也是使用Mcrypt加解密的,这一点需要注意。






  • 相关阅读:
    【Elasticsearch 技术分享】—— ES 常用名词及结构
    【Elasticsearch 技术分享】—— Elasticsearch ?倒排索引?这都是什么?
    除了读写锁,JUC 下面还有个 StampedLock!还不过来了解一下么?
    小伙伴想写个 IDEA 插件么?这些 API 了解一下!
    部署Microsoft.ReportViewe
    关于TFS强制undo他人check out
    几段查看数据库表占用硬盘空间的tsql
    How to perform validation on sumbit only
    TFS 2012 Disable Multiple Check-out
    在Chrome Console中加载jQuery
  • 原文地址:https://www.cnblogs.com/linewman/p/9918104.html
Copyright © 2011-2022 走看看