web-dev-qa-db-ja.com

PHP OpenSSLは、MySQL AES_ENCRYPT / DECRYPTを単独で使用するよりも安全ですか?

サーバーに保存されているMySQLデータベースのデータを暗号化/復号化したい。パスワードにソルトハッシュを使用しています。すべての暗号化/復号化はサーバーで行われます。私はリモートクライアントがアクセスするPHPエンドポイントを使用します。エンドポイントはMySQLデータベースにアクセスします。

次のPHPメッセージを暗号化/解読するためのコードがあります:

_<?php
    $key = "mySecretKey";
    $cipher = "aes-128-gcm";
    $ivlen = openssl_cipher_iv_length($cipher);

    $iv = openssl_random_pseudo_bytes($ivlen);
    $ciphertext = openssl_encrypt("message to be encrypted", $cipher, $key,     $options=0, $iv, $tag);

    $original_plaintext = openssl_decrypt($ciphertext, $cipher, $key, 0, $iv, $tag);

    echo "original message: ".$original_plaintext."\n";

    // $iv and $tag change each time we encrypt the data, so store these
?>
_

...暗号化されたデータをデータベースに保存するために使用していました。ただし、実行される_$iv_ごとにこれらの変更が行われるため、データとともに_$tag_および_openssl_encrypt_も格納する必要があります。

一方、MySQLの_AES_ENCRYPT_関数を使用することもできます。 SQLコードにAES_ENCRYPT(data, key)を追加するだけでよいので、このオプションはコードを大幅に簡略化します。

しかし、私はPHPソリューションは_AES_ENCRYPT_だけよりも安全であると感じています。これは本当ですか?

一方、私にはよくわかりません。たとえば、誰かが私の_AES_ENCRYPT_キーを手にした場合、簡単に私のPHP _$key_を手に入れることができます。この場合、 _openssl_encrypt_- edメッセージも復号化します。_$iv$_と_$tag_の情報は、何らかの形で_$key_を手に入れれば、おそらく簡単に手に入ります。 。

または、私はPHPソリューションを間違った方法で解決しようとしています。多分_$iv_は、情報を暗号化するたびに生成されるべきではありませんか?多分_$iv_は最終的なはずです、つまり常に同じです。この場合、_$tag_は常に同じです...

3
Pixel

MySQLサーバー側で暗号化を行う場合は、(暗号化されていない)データをMySQLサーバーに送信する必要があります。これを安全に行うには、転送中のデータを保護するために、MySQLサーバーへの暗号化された接続を確保する必要があります。設定によっては、データが(部分的に)どこかのログファイルに記録される可能性があります。これはすべて、セキュリティの利点を追加することなく、複雑さの層を追加します。

また、次もお読みください 「MySQLでAESを使用すべきでない理由」は正しいですか?


PHP sideで暗号化
PHP=側でデータを暗号化する場合、ユーザーフレンドリーなパッケージ( SymmetricEncryption または php-encryption 心に湧く)、そして暗号化された文字列をDBに格納するだけです。これはそれほど複雑ではありません。
たとえば、$iv、私は強く標準ライブラリを使用することをお勧めします!

つまり、要約すると、はい、PHP OpenSSLを使用すると、MySQL AES_ENCODE/DECODEより安全です。

4
Jacco

問題とそれを適切に使用する方法を完全に理解していない限り、 AES_ENCRYPT を使用しないでください!

AES_ENCRYPTにはいくつかの重要な問題があります:

デフォルトが貧弱です

デフォルト block_encryption_modeaes-128-ecbecbが何であるかを理解していて、それをデフォルトとしてここに表示する人は、おそらく今はうんざりしています。 significant の量の情報が漏洩する可能性があると言えば十分でしょう。

安全でない鍵の導出を推奨します

ドキュメント から:

パスフレーズを使用すると、パスフレーズをハッシュしてAESキーを生成できます。例えば:

INSERT INTO t
VALUES (1,AES_ENCRYPT('text', UNHEX(SHA2('My secret passphrase',512))));

パスワードまたはパスフレーズを直接crypt_strに渡さないで、最初にハッシュします。このドキュメントの以前のバージョンでは前者のアプローチが推奨されていましたが、ここに示す例の方が安全であるため、推奨されなくなりました。

どうやら以前はパスワードをキーとして直接使用することをお勧めしていました。今では、ソルトのない高速ハッシュ関数の単一の反復にそれを改善しました。なぜこれがかなりひどいのかについては here を参照してください。正しい方法は、PBKDF2などのパスワードベースのキー導出関数を使用することです。

認証された暗号化をサポートしていません

サポートされているモード は、ECB、CBC、CFB1、CFB8、CFB128、OFBです。これらのモードのほとんどは、ある程度柔軟であり、一部のモードでは、暗号文の特定のビットを反転して、平文の同じビットを反転できます。あなたの質問は、信頼性をチェックすることでこれを防ぐGCMを使用していることを示唆しています。

認証された暗号化を望まなかったとしても、私は個人的にそのような安全でないデフォルトと推奨事項で何かを使用することを避けたいと思います、そしてJacco 指摘 として、PHP PHPとMySQLの間の接続がTLSを使用することを保証できない場合は、より良い方法です。

3
AndrolGenhald