MySQLとPHPの相互暗号化・復号化

2019.02.08 11:09 ブログ

MySQLとPHPの相互暗号化・復号化の画像

データベースを暗号化する際に、MySQLのAES_ENCRYPTを主に使う様になるかと思います。
※AES_ENCRYPTを既に知っているのを前提としています。

そのAES_ENCRYPT(MySQL)で暗号化したものをPHPで復号化したい時に、少しハマったので記事にしておきます。
MySQLで復号化する際は下記の様になるかと思います。

#暗号化方式を指定 デフォルトは「aes-128-ebc」
SET block_encryption_mode = 'aes-128-ebc';
#暗号化してあるデータを復号化して取得
SELECT AES_DECRYPT(FROM_BASE64(カラム名), 'パスワード') FROM テーブル名
AES_DECRYPTの中にある「FROM_BASE64」がありますが、base64エンコードしてあるものを元に戻しています。
※AES_ENCRYPTで暗号化するとバイナリになっているので「FROM_BASE64」で文字列にしています。 「FROM_BASE64」としていますが、ネットでよく見かけるのは「UNHEX」かと思います。
なぜ「FROM_BASE64」を使用しているかと言いますと、PHPで暗号化したものをMySQLで復号化出来る様にしている為です。


PHPでの暗号化は、MySQLで復号化出来るのを前提としていますので、同じ暗号化方式が使える「openssl_encrypt」を使用します。
//暗号化するとBASE64エンコードされた状態で返却される
$result = openssl_encrypt("暗号化するデータ", "aes_128_ebc", "パスワード");
これでPHPで暗号化し、データベースにインサートしてMySQLで復号化する事が出来る様になったはず...と思っていたのですが
復号する事ができずハマりました。

すぐに結果を言ってしまいますが、原因はパスワードにありました。
PHPのopenssl_encryptはパスワードの部分が16桁までしか使用出来ず、16桁以上を入力すると16桁までで区切られて使用される様です。
その為、同じパスワードでも桁数が異なり、違うパスワードとされてしまい、復号化する事が出来ませんでした。

パスワードを16桁の同じ値に合わせて暗号化・復号化を行ってみた所、成功しました!


結論、気をつける点は下記の2つです。
・MySQLのAES_ENCRYPT・AES_DECRYPTのみだとバイナリになる
・PHPのopenssl_encrypt・openssl_decryptのパスワードは16桁まで

以上! PHPとMySQLの相互暗号化・復号化でした。