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("\0"),openssl自动使用PKCS7

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

 

二 算法演示

1 NUL("\0")填充算法

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

    /**
     * NUL("\0")填充算法
     * @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("\0", $pad);//KISS写法
            // pack 方法 a 模式使用 NUL("\0") 对内容进行填充  A 模式则使用空白字符填充
            $source .= pack("a{$pad}", ""); //高端写法
        }
        return $source;
    }


    /**
     * NUL("\0")填充算法移除
     * @param string $source
     * @return string
     */
    function stripZeroPadding($source)
    {
        return rtrim($source, "\0");
    }

 

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,要求待加密的数据长度已按"\0"填充与加密算法数据块长度对齐,即同mcrypt默认填充的方式一致,且对数据做base64编码处理(此模式下openssl要求待加密数据已按"\0"填充好,其并不会自动帮你填充数据)。

 

案例详解:

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 关闭资源退出

 

以上就是这次的全部内容

posted @ 2020-03-16 13:32  静小妞  阅读(2573)  评论(0编辑  收藏  举报