zoukankan      html  css  js  c++  java
  • php7废弃mcrypt加密,使用openssl替换

    概要:

    php从7.0升级到7.1废弃了一个扩展,即mcrypt扩展,虽然安装上扩展也能正常使用,但是会发出警告,告诉我们mcrypt相关方法已经被废弃,到了7.2,已经被移除,因此不建议继续使用。

    来源:

    在使用微信,淘宝第三方开发文档的时候,很多地方还是沿用以前的加密方法,这个时候我们需要找到替换的方法,openssl就是不错的选择,这就需要我们清楚mcrypt和openssl之间的差异,以便保证数据加解密的一致性。

    详解mcrypt和openssl来实现AES-128/192/256-CBC加解密:

    一 要点注意:

    1 使用何种填充算法。mcrypt自动使用NUL(""),openssl自动使用PKCS7

    2 是否对数据做了base64编码处理。mcrypt默认不使用,openssl默认使用

    二 算法演示

    1 NUL("")填充算法

    Mcrypt 的默认填充算法。NUL 即为 Ascii 表的编号为 0 的元素,即空元素,转移字符是 "",PHP 的 pack 打包函数在 'a' 模式下就是以 NUL 字符对内容进行填充的,当然,使用 "" 手动拼接也是可以的。

        /**
         * NUL("")填充算法
         * @param string $source
         * @param string $cipher
         * @param string $mode
         * @return string
         */
        public function addZeroPadding($source, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
        {
            $source = trim($source);
            // openssl 并没有提供加密cipher对应的数据块大小的api这点比较坑
            $block = mcrypt_get_block_size($cipher, $mode);
            $pad = $block - (strlen($source) % $block);
            if ($pad <= $block) {
                // $source .= str_repeat("", $pad);//KISS写法
                // pack 方法 a 模式使用 NUL("") 对内容进行填充  A 模式则使用空白字符填充
                $source .= pack("a{$pad}", ""); //高端写法
            }
            return $source;
        }
    
    
        /**
         * NUL("")填充算法移除
         * @param string $source
         * @return string
         */
        function stripZeroPadding($source)
        {
            return rtrim($source, "");
        }

    2 PKCS7 填充算法

    OpenSSL的默认填充算法。下面我们给出 PKCS7 填充算法 PHP 的实现

        /**
         * PKCS7填充算法
         * @param string $source
         * @param string $cipher
         * @param string $mode
         * @return string
         */
        function addPKCS7Padding($source, $cipher = MCRYPT_RIJNDAEL_128, $mode = MCRYPT_MODE_CBC)
        {
            $source = trim($source);
            $block = mcrypt_get_block_size($cipher, $mode);
            $pad = $block - (strlen($source) % $block);
            if ($pad <= $block) {
                $char = chr($pad);
                $source .= str_repeat($char, $pad);
            }
            return $source;
        }
    
        /**
         * 移去PKCS7填充算法
         * @param string $source
         * @return string
         */
        function stripPKSC7Padding($source)
        {
            $source = trim($source);
            $char = substr($source, -1);
            $num = ord($char);
            if ($num == 62) {
                return $source;
            }
    
            $source = substr($source, 0, -$num);
            return $source;
        }

    涉及知识讲解:

    1 AES详解:

    AES是当前最为常用的安全对称加密算法

    AES-128:16位密钥key

    AES-192:24位密钥key

    AES-256:32位密钥key

    即算法统一使用MCRYPT_RIJNDAEL_128,并通过key的位数来选定是以何种AES标准加密,iv固定16位(openssl的AES加密iv始终为16位),mode选用CBC模式

    2 openssl讲解:

    openssl是一个功能强大的工具包,它集成了众多算法,我们既可以利用它提供的命令台工具生成密钥,证书来加解密文件,也可以利用其提供的API接口在代码中对传输信息进行加密。mctypt需要将加密算法分为cipher+mode去指定,openssl则只需要直接指定method即可。并且提供了三种处理模式,即默认模式0/OPENSSL_RAW_DATA/OPENSSL_ZERO_PADDING。

    openssl加解密函数中,options参数尤为重要,它是兼容mcrypt算法的关键:

    options = 0:默认模式,自动对明文进行pkcs7 padding,且数据做base64编码处理

    options = 1:OPENSSL_RAW_DATA,自动对明文进行pkcs7 padding,数据未经base64编码处理

    options = 2:OPENSSL_ZERO_PADDING,要求待加密的数据长度已按""填充与加密算法数据块长度对齐,即同mcrypt默认填充的方式一致,且对数据做base64编码处理(此模式下openssl要求待加密数据已按""填充好,其并不会自动帮你填充数据)。

    案例详解:

    mcrypt加密

    private static $iv = “1122334455667788";
    
    public static function encrypt($input, $key) {
        $key = base64_decode($key);
        $localIV = Security::$iv;
        $module = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, $localIV);
        mcrypt_generic_init($module, $key, $localIV);
        $size = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        $pad = $size - (strlen($input) % $size);
        $input . str_repeat(chr($pad), $pad);
        $data = mcrypt_generic($module, $input);
    
        mcrypt_generic_deinit($module);
        mcrypt_module_close($module);
        $data = base64_encode($data);
        return $data;
    }

    openssl解密

    private $hex_iv = '0102030405060708';
    private $key = '';
    
    public function decrypt_($input)
    {
      $input = base64_decode($input);
      $decrypted = openssl_decrypt(
          $input,
        'AES-128-CBC',
        $this->key,
        OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING,
          $this->hex_iv
      );
      $dec_s = strlen($decrypted);
      $padding = ord($decrypted[$dec_s-1]);
      $decrypted = substr($decrypted, 0, -$padding);
      return $decrypted;
    }

    mcrypt相关函数详解:

    mcrypt_module_open 打开加密算法和模式

    参数1使用加密算法的名称,对应mcrypt_list_algorithms()输出的加密算法;参数3支持的加密模式,对应mcrypt_list_modes()输出的加密模式

    mcrypt_generic_init 初始化加密缓冲区

    参数1为返回的加密描述符,参数2为加密密钥,参数3为初始化向量

    mcrypt_get_block_size 取得编码方式的区块大小

    参数1为加密算法,参数3为加密模式

    mcrypt_generic 数据加密

    参数1为返回的加密描述符,参数2为加密钱的数据,返回加密后字符串

    mcrypt_generic_deinit 结束加密,执行清理工作

    mcrypt_module_close 关闭资源退出

    以上就是这次的全部内容

  • 相关阅读:
    考试
    学习笔记
    Seajs使用实例入门介绍
    使用属性选择器用于空链接 &如何做1像素细边框的table?
    简单制作U盘启动盘安装Ghost XP系统(大白菜+深度)
    Access-Control-Allow-Origin这个header这个头不能设置通配符域名
    windows查找svchost到底代表的是哪个服务
    可观察对象(Observable)
    [ flask ] flask-restful 实现嵌套的有关系的输出字段
    [ vue ] quasar框架踩坑:在vue文件外导入路由,执行router.push('/')没有效果
  • 原文地址:https://www.cnblogs.com/jingxiaoniu/p/12217789.html
Copyright © 2011-2022 走看看