株式会社タフス

暗号化方式の振り替え: mcryptからopensslへ

背景

PHPのmcrypt拡張が非推奨となり、今後の互換性を考慮してopensslへの移行を行う必要がありました。既存のシステムではmcryptを使用してデータを暗号化しており、これをopensslを使った暗号化に置き換えることで、同じ結果が得られるようにしたいという課題がありました。

課題

  • mcryptを使用して暗号化されたデータをopensslを使用して同じ結果を得る
  • 特に、AES-128-ECBモードでの暗号化が求められた

移行方法

以下の手順でmcryptからopensslへの移行を行いました。

mcryptでの暗号化
function enCrypt($str) {
    $urlEncode = "";
    if ($str == "" || strlen($str) == 0) {
        return $urlEncode;
    }
    $conf = Zend_Registry::get('crypt');
    $key = $conf['key'];
    $keycheck = $this->_keyCheck($key);
    $text = $str;

    srand();
    $size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_ECB);
    $iv = mcrypt_create_iv($size, MCRYPT_RAND);

    try{
        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_ECB, $iv);
        $hex = bin2hex($encrypted);
        $urlEncode = urlencode($hex);
    } catch (Exception $e) {
        throw new SystemException("暗号化処理で失敗しました。",SystemException::EXCEPTION_SYSTEM_ERROR);
    }
    return $urlEncode;
}


opensslでの暗号化
function paddingZero($plane) {
    if (strlen($plane) % 16) {
        $plane = str_pad($plane, strlen($plane) + 16 - strlen($plane) % 16, "\0");
    }
    return $plane;
}

function enCrypt($str, $key) {
    if ($str == "" || strlen($str) == 0) {
        return "";
    }

    $paddedStr = paddingZero($str);

    $encrypted = openssl_encrypt($paddedStr, 'aes-128-ecb', $key, OPENSSL_RAW_DATA);
    $hex = bin2hex($encrypted);
    return urlencode($hex);
}

$key = '************';
$password = '***********';

$encrypted_password = enCrypt($password, $key);
echo "暗号化されたパスワード: $encrypted_password\n";

$expected_value = '******************************';
if ($encrypted_password === $expected_value) {
    echo "暗号化されたパスワードは期待通りの値と一致します。\n";
} else {
    echo "暗号化されたパスワードは期待通りの値と一致しません。\n";
}


結果

  • mcryptopensslで同じ暗号化結果を得るためには、適切なパディングとモードを一致させる必要があります。
  • 上記のopensslを使用したコードにより、既存のmcryptによる暗号化結果と一致させることができました。

この移行により、PHPの最新バージョンでも互換性のある安全な暗号化が実現できました。