PHP 7.1ではopensslでmcryptを置換します.


PHP 7.1ではopensslでmcryptを置換します.
php開発では、mcrypt関連関数を使ってAESプラス、解読操作が容易に行えますが、PHP 7.1ではmcrypt拡張が廃棄されていますので、他の実現を探さなければなりません.移動マニュアルではmcryptの代わりにopensslを使用することが指摘されていますが、具体的な例はありません.ネット上では多くの例がありますが、ほとんどのシーンを置き換えることができますが、詳細については説明していません.同様に、オンラインの例を簡単に使用すると、コードの交換前後の互換性があります.以下では、具体的なコードと理由について説明します.
まず私たちは直接に代替コードを与えて、コードから問題を分析します.(本論文で分析したアルゴリズムはAES-128-CBC)
置換例
例としては、2つのmcryptの使用方法が示されていますが、主に異なる充填(以下、充填を説明します).全体のプラス、解読の過程で、完全度の高いコードは自主的に充填、除去充填を実現し、簡単なコードは直接に充填を無視しますが、二つの方法は正常に実行できます.実際の開発では(7.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, '', 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';
    
            return bin2hex(openssl_encrypt($data, 'AES-256-CBC', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv));
    
  • 上記の例では、最初の例(塗りつぶしは使用されていませんが、opensslで充填されています)と第二の例(塗りつぶしを使用して、opensslでは塗りつぶしは使用されていません)は、置換前後に同じ出力されていますので、互換性はありません.コードによって異なりますが、3つの詳細については説明が必要です.
  • はなぜ充填が必要ですか?
  • opensslで置換した後のアルゴリズムの名前はなぜ違いますか?
  • 次に充填、アルゴリズムを具体的に分析します.
    塗りつぶし
    なぜ塗りつぶしがあるのかは暗号化のアルゴリズムから話します.AES-128-CBCアルゴリズムでは、暗号化する文字列を16 byte毎の長さで段階的に計算し、16 byte未満のセグメントを充填するからである.したがって、与えられた例の中には、デフォルトのパディングを使用するものと、自主的にパディングするものがあります.opensslとの交替において、どのように充填方案を選択するかについては、mcryptとopensslがデフォルトと自主充填について知っている必要があります.
  • mcryptは標準的にphpのソースコードに充填されています.デフォルトは\x00で充填されていることが分かります.実際には\x00で充填されていません.ソースから確認できます.まず16桁の空の文字列を申請したので、初期化時は1バイト当たり\x00です.実際には充填されていません.ただ、元々は\x00です.デフォルトの塗りつぶしを使って得られた暗号化文字列は、以下のような形式になります.したがって、復号時には余分な\x00を除去します.もちろん怠惰なこともできます.\x00を除去しません.phpにおいて文字列「strigx 00」と文字列「string」は長さが異なる以外、他の表現は全て一致しているので、以下のような区別はなさそうです.
  • mcrypt自主充填アルゴリズムは、次のようなアルゴリズムで行われる必要があります.
  • パディング
       //        `\x00`      true
       if ("string\x00" == "string") { //        \x00
           echo true;
       }
    
            /**
             *     
             * @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;
            }
  • に参加します.
  • 充填
  • を除去する.
  • opensslデフォルトでは標準のmcryptの自主的な充填方式と一致していますので、第二の例では、上記のようなパディングアルゴリズムを使用した後、直接にopenssl_を使用することができます.encryptの入れ替えは、互換性の問題が発生しません.充填後の暗号化文字列は以下のような形式である.\x00\x00に充填と除去充填が内蔵されているので、直接使用すればよく、自主的に充填を実現する必要がない限り、充填
  • を考慮する必要はない.
  • openssl自主充填openssl_encryptは、Ooptionパラメータを提供して、自主的な充填をサポートしていますが、phpのソースコードの中のopensslのテスト用コードを調べて、正しい使い方を見つけました.encryptは以前に自主点チャージopenssl_encryptのコードを加入しました.原因は
  • です.
    以上の加法、復号化は、パディングロジックに対して異なるので、上記の例についてよく説明することができる.
  • 例1:mcrypt暗号化では充填が使用されていないため、openssl_decryptで充填されているので、opensslに換えるには、自主的にOPENSSL_ZERO_PADDINGを充填する必要があります.
  • 例2:mcrypt暗号化には標準的な充填が使用されていますが、opensslの充填方法も標準的に充填されていますので、そのまま使用すればいいです.
  • これを分析すると、どのようなパディング戦略であれ、暗号化時にパディングを追加することに注意が必要であり、復号時にパディングを除去しなければならないことが分かります.以上のように、上記の例での充填相関の解析が完了しました.次に、代替アルゴリズムの選択方法を確認します.
    アルゴリズムを選択
    以上の例では、mcryptのAES-128-CBCアルゴリズムが、opensslでAES_にどのように置き換えられているかという問題がある.256この点について、私も合理的な説明を見つけられませんでした.ソースを調べても、一時的には原因が見つかりませんでした.しかし、以下の資料を通して、機能が完成しました.
  • openssl解読mcrypt AESデータ不適合問題
  • Convert mcrypt_generic to openssl_encrypt Ask Question
  • もし友達が原因を見つけたら、メッセージをください.ありがとうございます.
    締め括りをつける
    mcrypt AESを用いて暗号化されている部分については、代替過程において問題があれば、アルゴリズムから代替または充填することができると考えられる.また、満たしていなければならない条件は、充填方式によって選択されます.一番重要なのは互換性の問題を考慮して、交換後は何も変化しないことを保証します.わずかな違いがあるだけです.末尾のいくつかの文字列の違いがありますが、複数のプラットフォームの中で同時に修正するのは面倒なことですが、変動が少ないほどリスクが小さいです.
    本論文ではAESアルゴリズムについて簡単に説明しただけで、他のアルゴリズムが適用されるかどうかはまだ検討されている.
    参考資料
    PHP 7.1.xにおける廃棄の特性:http://www.php.net/manual/zh/migration71.deprecated.php mcrypt拡張廃棄:http://www.php.net/manual/zh/book.mcrypt.php AESアルゴリズム:https://blog.csdn.net/qq_2820153/articale/detail/55798628 mcryptソース:https://github.com/php/php-src/blob/php-7.0.30/ext/mcrypt/mcrypt.c openssl拡張元コード:https://github.com/php/php-src/blob/master/ext/openssl/openssl.c openssl解読mcrypt AESデータの互換性がない問題:https://www.v2ex.com/t/370493 Covert mcrypt(u)generic to openssl_encrypt Ask Question:https://stackoverflow.com/questions/48800725/convert-mcrypt-generic-to-openssl-encrypt