Mcrypt が使えなくて困った
すでに数年前の話なのですが、Laravel の古いバージョンで実装したけれどそのまま放置気味だった Web アプリケーションを改修しようとしたところ、暗号化・復号でトラブルがあったというログです。
過去、 PHP では暗号化・復号ライブラリとして Mcrypt
を使用しており、 Laravel でもこのライブラリに依存した実装がありました。
稼働実績のあるその Web アプリケーションでは Mcrypt
で暗号化したデータがデータベースに大量保存されています。
この Mcrypt
は⻑期間メンテナンスいなかったため、 PHP 7.2 で削除されました。
Mcrypt
に変わるものが OpenSSL
ですが、 Mcrypt
と OpenSSL
は単純に置き換えができなく、泣きつかれた感じです。
結論としては、互換性があるので OK です。
暗号化結果の⽐較
Mcrypt で暗号化
リプレイス前に動作していたものと同等のコードです。
1// 暗号化するデータ
2$plaintext = 'dummy_text';
3// シークレットキー
4$key = 'dummy_secret_key';
5
6$ciphertext = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $plaintext, MCRYPT_MODE_ECB);
7$ciphertext_base64 = base64_encode($ciphertext);
8
9echo $ciphertext_base64; // dD2hL+qY2lG60wM7vQW0fQ==
OpenSSL で暗号化
リプレイス後のコードです。
1// 暗号化するデータ
2$plaintext = 'dummy_text';
3// シークレットキー
4$key = 'dummy_secret_key';
5// 同等の暗号メソッド
6$cipher = "aes-128-ecb";
7
8$ciphertext = openssl_encrypt($plaintext, $cipher, $key, OPENSSL_RAW_DATA);
9$ciphertext_base64 = base64_encode($ciphertext);
10
11echo $ciphertext_base64; // srIFQhnoDAIgRJOefeES4Q==
暗号化メソッドは同等にしていますが、暗号化で得られる文字列の結果が違っています。
復号する
しかし、すでに述べている通り、結果は違いますが復号は可能です。
Mcrypt で復号する
mcrypt_encrypt()
で暗号化したものは、対応する mcrypt_decrypt()
なら当然復号できます。
1// 暗号化済み文字列
2$ciphertext_base64 = 'dD2hL+qY2lG60wM7vQW0fQ==';
3// シークレットキー
4$key = 'dummy_secret_key';
5
6$ciphertext_dec = base64_decode($ciphertext_base64);
7$plaintext_dec = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext_dec, MCRYPT_MODE_ECB);
8
9echo $plaintext_dec; // dummy_text
復号できることが確認できました。
なお、 OpenSSL
で暗号化したものを、上のコードで復号もできます。
ただし OPENSSL_ZERO_PADDING をオプション指定しないと失敗します。
OpenSSL で復号する
では Mcrypt
で暗号化したものを OpenSSL
で復号します。
1// 暗号化済み文字列
2$ciphertext_base64 = 'dD2hL+qY2lG60wM7vQW0fQ==';
3// シークレットキー
4$key = 'dummy_secret_key';
5// 同等の暗号メソッド
6$cipher = "aes-128-ecb";
7
8$ciphertext_dec = base64_decode($ciphertext_base64);
9$plaintext_dec = openssl_decrypt($ciphertext_dec, $cipher, $key, OPENSSL_RAW_DATA);
10
11echo $plaintext_dec; // dummy_text
おお、復号できました。
OK ですね。
最初⼀瞬⾎の気が引いたのですが、互換性があって問題なくやり取りできるよ、ということのログでした。