ホームページ >バックエンド開発 >PHPチュートリアル >PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要

PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要

不言
不言オリジナル
2018-07-04 14:10:382230ブラウズ

この記事では主に PHP7.1 の mcrypt を openssl で置き換える方法を紹介します。参考になる値があるので共有します。困っている友人は参考にしてください。

PHP7.1 で openssl を使用して mcrypt を置き換えます

PHP 開発では、mcrypt 関連関数を使用すると AES 暗号化および復号化操作を簡単に実行できますが、mcrypt 拡張機能は PHP7.1 では廃止されたため、別の種類の認識。 mcrypt を openssl に置き換えることは移行マニュアルですでに指摘されていますが、具体的な例は示されていません。ほとんどのシナリオを置き換えることができる例がオンラインに多数ありますが、詳細は説明されていません。同様に、オンラインのサンプルを使用するだけでは、特定のコード シナリオでのコード置換の前後で互換性の問題が発生する可能性があります。具体的なコードとその理由については、以下で説明します。

まず、置換コードを直接与えてから、コードから問題を分析します。 (この記事で分析するアルゴリズムは AES-128-CBC です)

置換例

この例では、主に filling で mcrypt を使用する 2 つの方法を示します。 異なります (filling については以下で説明します)。暗号化と復号化のプロセス全体で、より完全なコードは埋め込みと埋め込みの削除を自動的に実装し、より単純なコードは埋め込みを直接無視しますが、どちらの方法も正常に実行できます。実際の開発 (7.1 より前のバージョン) では、これをお勧めします。パディングを追加します。次の具体的な例を参照してください:

  1. #mcrypt はパディングを使用しません

  • ##mcrypt 暗号化:

      $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);

  • 同じ機能を持つ OpenSSL 暗号化コード:

      $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));

  • mcrypt はパディングを使用します

    • mcrypt 暗号化:

        $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, &#39;&#39;, MCRYPT_MODE_CBC, &#39;&#39;);
        mcrypt_generic_init($cipher, $key, $iv);
        $cipherText256 = mcrypt_generic($cipher, $data);
        mcrypt_generic_deinit($cipher);
      
        return bin2hex($cipherText256);

    • 同じ関数の OpenSSL 暗号化コード:

        $key = &#39;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#39;; 
        $iv = &#39;aaaaaaaaaaaaaaaa&#39;;
        $data = &#39;dataString&#39;;
      
        return bin2hex(openssl_encrypt($data, &#39;AES-256-CBC&#39;, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));

    上記の例は、最初の例 (パディングなし) で正常に実行できます。が使用されていますが、openssl でパディングあり) と 2 番目の例 (openssl でパディングあり、パディングなし) の出力は置換前後で同じであり、互換性の問題はありません。コードのさまざまな充填方法に基づいてさまざまな置換ソリューションを選択できますが、説明する必要がある 3 つの詳細があります。

    1. なぜ充填するのか?

    2. openssl に置き換えた後、アルゴリズムの名前が異なるのはなぜですか?

    以下は、

    fillingalgorithm の詳細な分析です。

    パディング

    パディングが存在する理由は、暗号化アルゴリズムから始まります。 AES-128-CBC アルゴリズムでは、暗号化される文字列が長さ 16 バイトごとのセグメントに分割され、段階的に計算されるため、16 バイト未満のセグメントが埋められることになります。したがって、2 種類の例が示されています。1 つはデフォルトの塗りつぶしを使用するもので、もう 1 つは独立した塗りつぶしを使用するものです。 openssl への置き換えでは、パディング スキームを選択する方法には、mcrypt と openssl のデフォルトおよび自律的なパディングを理解する必要があります。

    • mcrypt のデフォルトの塗りつぶし

      php のソース コードでは、デフォルトの塗りつぶしが

      \x00 であることがわかります。 \x00 で埋められていません。ソース コードから、16 ビットの空の文字列が最初に適用されていることがわかります。そのため、初期化中に各バイトは \x00 になります。実際には、パディングはありませんが、元々は \x00 であるとも言えます。デフォルトのパディングを使用して取得された暗号化文字列は、次の形式になります。 # なので、Extra
      \x00PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要 を復号化するときに削除する必要があります。もちろん、怠けて

      \x00

      を削除しないこともできます。 PHP では、文字列 "string\x00" と文字列 "string" は長さ以外は同じように動作するため、違いはないようです。次のコード: <pre class="brush:php;toolbar:false">   // 尾部包含若干个`\x00` 均可功输出true    if (&quot;string\x00&quot; == &quot;string&quot;) { // 用双引号可解析\x00        echo true;    }</pre>\x00 パディング後の例: (文字列の長さに注意してください。

      \x00

      でパディングすると長さに影響することがわかります)
      PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要mcrypt 自律充填

    • 充填アルゴリズムは次のアルゴリズムに従って実行する必要があります:
    • パディングを追加しました
    •   /**
         * 填充算法
         * @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;
        }
        パディングを追加した後の文字列は、実際には次のようになります。 形式:

      • PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要パディングを削除

          /**
           * 移去填充算法
           * @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;
          }
      • openssl のデフォルト パディング
      そのデフォルト このメソッドは、標準の mcrypt の独立した埋め込みメソッドと一貫しているため、2 番目の例では、上記の埋め込みアルゴリズムを使用した後、互換性の問題を引き起こすことなく openssl_encrypt に直接置き換えることができます。埋め込まれた暗号化文字列は次の形式になります:
    • これは PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要openssl_encrypt

      および

      に組み込まれていることに注意してください。 openssl_decrypt 塗りつぶしと塗りつぶしを削除するため、直接使用できます。塗りつぶしを個別に実装する必要がない限り、塗りつぶしを考慮する必要はありません openssl 自律充填

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

         // if we want to manage our own padding
        $padded_data = $data . str_repeat(&#39; &#39;, 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));

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

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

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

    • 示例2:
      mcrypt加密时使用了标准的填充,同时openssl的填充方式也为PHP7.1 で openssl を使用して mcrypt を置き換える方法の概要,故直接使用即可。

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

    选择算法

    在以上的示例中,有一个问题在于,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添加文章固定字段的介绍

    以上がPHP7.1 で openssl を使用して mcrypt を置き換える方法の概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    声明:
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。