PHP
mcrypt
PHP7.2
phpderkaigi2018

PHP 7.2で消えるMcryptの扱い

deprecated(非推奨)を放置してませんか?

  • deprecatedにされた関数は、最後は消える運命にあります。
  • Mcryptも、http://php.net/manual/ja/migration71.deprecated.php のページに書かれているように、非推奨後に削除されることが記載されていました。

mcrypt 拡張モジュールは十年近くにわたって放置されており、極めて使いづらいものです。 そこで、この拡張モジュールを非推奨にしました。かわりに OpenSSL を使いましょう。 mcryptは PHP 7.2 でコアから削除されて、PECL に移る予定です。

  • 10年も放置ということは、 正直言ってPECLに行って使い続けるのも不安です。
  • この際、思い切って推奨しているOpenSSLに行こうじゃないですか?!

Mcryptはいきなり来た

  • そもそも、Mcryptは唐突に廃止のアナウンスがきたような気がします。
  • 確認すると、PHP 7.1.0で非推奨、PHP 7.2.0で廃止となりました!
  • モジュールの削除なのに、マイナーバージョンアップでくるとは、意外といきなりでした。
  • This feature was DEPRECATED in PHP 7.1.0, and REMOVED in PHP 7.2.0. FireShot Capture 6 - PHP_ はじめに - Manual - http___php.net_manual_ja_intro.mcrypt.php.png

この先生きのこるには?

  • 選択肢は3つ!
    1. PECLに頼る。
    2. データを初期化して、opensslに行く。
    3. データを初期化せずに、opensslに行く。

データを初期化せずに、opensslに行く。

  • せっかくだから俺はこの 赤の扉 「データを初期化せずに、opensslに行く」を選ぶぜ!
  • 行けるのか?試してみた!
  • とりあえず、簡単に試してみたいのでecbモードでやります。
test_code.php
<?php
$message = 'テストするための文字';
$key = '01234567890123456789012345678901234567890';

// opensslの利用可能な暗号メソッドを取得
$ciphers             = openssl_get_cipher_methods();

// mcryptの利用可能な暗号メソッドを取得
$algorithms = mcrypt_list_algorithms();

// mcryptの暗号の分、ループする
foreach($algorithms as $mcrypt_method) {
  // ブロックサイズ0は今回は対象外
  $size = @mcrypt_get_block_size($mcrypt_method , 'ecb');
  if ($size == null) {
  } else {

    echo "mcrypt_method: ${mcrypt_method} \n";
    echo "input message: {$message} \n";
    // 暗号化する文字列を取得したブロックサイズでpaddingする
    $padding_message = pkcs5_pad($message , $size);
    // mcrypt_get_key_sizeで、最小のキー長さを取得し、その長さをキーとする
    $setting_key = substr ($key , 0, mcrypt_get_key_size($mcrypt_method, 'ecb'));
    // mcryptで暗号化実行
    $crypto = base64_encode(mcrypt_encrypt($mcrypt_method, $setting_key, $padding_message, MCRYPT_MODE_ECB));

    // opensslで確認する
    $has_decrypt = false;

    // opensslの暗号の分、ループする
    foreach($ciphers as $openssl_method) {
       if (preg_match('/ecb\z/', $openssl_method)) {
         // decryptする
         $decrypt = openssl_decrypt($crypto, $openssl_method ,$setting_key );
         // decryptして入力文字列と一致したらOKとする
         if ($message == $decrypt) {
            echo "openssl_method: ${openssl_method} is OK\n";
            echo "decrypt message: {$decrypt} \n\n";
            $has_decrypt = true;
            break;
         }
      }
    }
    if ($has_decrypt == false) {
       echo "openssl_method: not decrypt \n\n";
    }
  }
}

function pkcs5_pad ($text, $blocksize)
{
    $pad = $blocksize - (strlen($text) % $blocksize);
    return $text . str_repeat(chr($pad), $pad);
}

結果

mcrypt_method: cast-128 
input message: テストするための文字 
openssl_method: cast5-ecb is OK
decrypt message: テストするための文字 

mcrypt_method: gost 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: rijndael-128 
input message: テストするための文字 
openssl_method: aes-256-ecb is OK
decrypt message: テストするための文字 

mcrypt_method: twofish 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: cast-256 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: loki97 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: rijndael-192 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: saferplus 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: blowfish-compat 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: des 
input message: テストするための文字 
openssl_method: des-ecb is OK
decrypt message: テストするための文字 

mcrypt_method: rijndael-256 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: serpent 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: xtea 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: blowfish 
input message: テストするための文字 
openssl_method: bf-ecb is OK
decrypt message: テストするための文字 

mcrypt_method: rc2 
input message: テストするための文字 
openssl_method: not decrypt 

mcrypt_method: tripledes 
input message: テストするための文字 
openssl_method: not decrypt 

4つ行ける!

mcrypt_method openssl_method
cast-128 cast5
rijndael-128 aes-256
des des
blowfish bf
  • 自分が担当しているのはシステムで使っているのは、desとblowfishとrijndael-192・・・あれ?
  • rijndael-192はダメか・・・諦めるかな?←こちら、うまくいかなかった理由は未検証です。
  • PHP 5.3.0 ぐらいから、非推奨としてくれてたら、間に合ったかもしれませんが、後の祭りです。