Introduction to using openssl to replace mcrypt in PHP7.1

不言
Release: 2023-04-02 10:48:01
Original
1856 people have browsed it

This article mainly introduces the introduction of using openssl to replace mcrypt in PHP7.1. It has a certain reference value. Now I share it with you. Friends in need can refer to it

Use openssl to replace mcrypt in PHP7.1

In PHP development, using mcrypt related functions can easily perform AES encryption and decryption operations, but the mcrypt extension is abandoned in PHP7.1, so you must find another kind of realization. Replacing mcrypt with openssl is already pointed out in the migration manual, but no specific example is given. There are many examples online that can replace most scenarios, but the details are not explained. Similarly, simply using online examples may lead to compatibility issues before and after code replacement in certain code scenarios. Let’s talk about the specific codes and reasons below.

First we give the replacement code directly, and then analyze the problem from the code. (The algorithm analyzed in this article is AES-128-CBC)

Replacement example

The example will show two ways of using mcrypt, mainly in fillingDifferent (filling will be explained below). During the entire encryption and decryption process, a more complete code will automatically implement filling and removal of filling, and a simpler code will directly ignore the filling, but both methods can run normally; in actual development (versions before 7.1), It is recommended to add padding. Please see the following specific example:

  1. mcrypt does not use padding

  • ##mcrypt encryption:

      $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
      $iv = 'aaaaaaaaaaaaaaaa';
      $data = 'dataString';
    
      $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
      mcrypt_generic_init($cipher, $key, $iv);
      $cipherText256 = mcrypt_generic($cipher, $data);
      mcrypt_generic_deinit($cipher);
    
      return bin2hex($cipherText256);
    Copy after login

  • Openssl encryption code with the same function:

      $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
      $iv = 'aaaaaaaaaaaaaaaa';
      $data = 'dataString';
    
      $data = $data . str_repeat("\x00", 16 - (strlen($data) % 16)); // 双引号可以解析asc-ii码\x00
    
      return bin2hex(openssl_encrypt($data, "AES-256-CBC", $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
    Copy after login

  • mcrypt uses padding

    • mcrypt encryption:

        $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
        $iv = 'aaaaaaaaaaaaaaaa';
        $data = 'dataString';
      
        // 填充(移除填充反着移除即可)
        $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
      
        $pad = $block - (strlen($data) % $block);
        if ($pad <= $block) {
            $char = chr($pad);
            $data .= str_repeat($char, $pad);
        }
      
        $cipher = mcrypt_module_open(MCRYPT_RIJNDAEL_128, '', MCRYPT_MODE_CBC, '');
        mcrypt_generic_init($cipher, $key, $iv);
        $cipherText256 = mcrypt_generic($cipher, $data);
        mcrypt_generic_deinit($cipher);
      
        return bin2hex($cipherText256);
      Copy after login

    • OpenSSL encryption code for the same function:

        $key = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'; 
        $iv = 'aaaaaaaaaaaaaaaa';
        $data = 'dataString';
      
        return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
      Copy after login

    The above examples can be run successfully, the first example (no padding is used, But with padding in openssl) and the second example (with padding, without padding in openssl) the output is the same before and after replacement, and there are no compatibility issues. You can choose different replacement plans based on the different filling methods of the code, but there are three details that need to be explained

    1. Why is there filling?

    2. Why are the names of the algorithms different after replacing them with openssl?

    The following will be a detailed analysis of

    filling and algorithm.

    Padding

    Why there is padding starts with the encryption algorithm. Because in the AES-128-CBC algorithm, the string to be encrypted will be segmented into segments every 16 bytes in length and calculated step by step, resulting in segments less than 16 bytes being filled. So there are two types of examples given: one is to use the default filling, and the other is to use independent filling. In the replacement with openssl, how to choose the padding scheme requires understanding of the default and autonomous padding of mcrypt and openssl.

    • mcrypt default filling

      In the source code of php, it can be seen that the default filling will be

      \x00. In fact, it is not filled with \x00 is filled. It can be found from the source code that a 16-bit empty string is first applied for, so each byte is \x00 during initialization. In fact, it can be said There is no padding, but it is originally \x00. The encrypted string obtained by using the default padding will be in the following form:
      Introduction to using openssl to replace mcrypt in PHP7.1

      , so it must be removed when decrypting Extra

      \x00. Of course, you can also be lazy and not remove \x00. Because in php, the string "string\x00" and the string "string" behave the same except for the length, so there seems to be no difference. The following code:

         // 尾部包含若干个`\x00` 均可功输出true
         if ("string\x00" == "string") { // 用双引号可解析\x00
             echo true;
         }
      Copy after login

      \x00 Example after padding: (Please pay attention to the length of the string, it can be seen that padding with \x00 will affect the length)
      Introduction to using openssl to replace mcrypt in PHP7.1

    • mcrypt Autonomous Filling

      The filling algorithm needs to be carried out according to the following algorithm:

      • Added padding

          /**
           * 填充算法
           * @param string $source
           * @return string
           */
          function addPKCS7Padding($source)
          {
              $source = trim($source);
              $block = mcrypt_get_block_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
        
              $pad = $block - (strlen($source) % $block);
              if ($pad <= $block) {
                  $char = chr($pad);
                  $source .= str_repeat($char, $pad);
              }
              return $source;
          }
        Copy after login

        After adding padding, the string is actually as follows Form:


        Introduction to using openssl to replace mcrypt in PHP7.1

      • remove padding

          /**
           * 移去填充算法
           * @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;
          }
        Copy after login

    • openssl default padding

      its default The method is consistent with the standard mcrypt's independent filling method, so in the second example, after using the above filling algorithm, it can be directly replaced by openssl_encrypt without causing compatibility issues. The filled encrypted string is in the following form:

      Introduction to using openssl to replace mcrypt in PHP7.1

      It should be noted that it is built-in in openssl_encrypt and openssl_decrypt Filling and removing filling, so you can use it directly. Unless you need to implement filling independently, there is no need to consider filling

    • openssl autonomous filling

      openssl_encrypt提供了option参数以支持自主填充,但在查阅php源码中openssl的测试用例代码才找到正确用法:

         // if we want to manage our own padding
        $padded_data = $data . str_repeat(' ', 16 - (strlen($data) % 16));
        $encrypted = openssl_encrypt($padded_data, $method,     $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
        $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv);
        var_dump(rtrim($output));
      Copy after login

      (备注:如上,OPENSSL_ZERO_PADDING 并非是为0填充的意思)
      由此,我们就可以解释,在第一个示例中openssl_encrypt之前加入了自主点充\x00的代码原因了

    从以上的加、解密针对填充逻辑不同,针对上文中的示例可以很好地解释:

    • 示例1:
      mcrypt加密时未使用填充,故以\x00进行了填充,所以在替换成openssl,需要自主实现\x00填充。

    • 示例2:
      mcrypt加密时使用了标准的填充,同时openssl的填充方式也为Introduction to using openssl to replace mcrypt in PHP7.1,故直接使用即可。

    分析到这,可以发现,无论是何种填充策略都需注意在加密时加入填充,在解密时则必须要移除填充。至此,上文中示例中的填充相关则分析完成了,接下来我们再看看如何选择替换后的算法。

    选择算法

    在以上的示例中,有一个问题在于,mcrypt中的AES-128-CBC算法,在openssl中怎么替换成了AES_256?
    关于这一点, 我也未找到合理的解释,查看源码一时半会也没找到原因(能力有限~),但通过以下资料,还是完成了功能

    • openssl 解密 mcrypt AES 数据不兼容问题

    • Convert mcrypt_generic to openssl_encrypt Ask Question

    若是有同学找到原因,欢迎给我留言,谢谢。

    总结

    对于使用mcrypt AES 进行加密密的部分,若是在替换过程中问题, 可以从算法替换或填充这两方面着手考虑下。同时还是一必须满足的条件是根据不同的填充方式选择, 替换最重要的就要考虑兼容问题,保证替换后不发生任何改变。 虽然只是只是有细微的差别----尾部几个字符串的不同,但若是在多平台中同时进行修改也是一件麻烦事,但变动越少风险越小。

    本文只是针对AES算法进行了简单说明,对于其他算法是否适用还有待研究。

    以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

    相关推荐:

    PHP Excel导入数据到MySQL数据库的方法

    wordpress添加文章固定字段的介绍

    The above is the detailed content of Introduction to using openssl to replace mcrypt in PHP7.1. For more information, please follow other related articles on the PHP Chinese website!

    Related labels:
    source:php.cn
    Statement of this Website
    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
    Popular Tutorials
    More>
    Latest Downloads
    More>
    Web Effects
    Website Source Code
    Website Materials
    Front End Template
    About us Disclaimer Sitemap
    php.cn:Public welfare online PHP training,Help PHP learners grow quickly!