82

私はこの質問を見て、自分でやりたかったのです。このコードを実行したとき(この回答から直接取得):

$textToEncrypt = "My super secret information.";
$encryptionMethod = "AES-256-CBC";  // AES is used by the U.S. gov't to encrypt top secret documents.
$secretHash = "25c6c7ff35b9979b151f2136cd13b0ff";

//To encrypt
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, '1234567812345678');

//To Decrypt
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash);

//Result
echo "Encrypted: $encryptedMessage <br>Decrypted: $decryptedMessage";

しかし、私は警告を受けます

openssl_encrypt(): Using an empty Initialization Vector (iv) is potentially insecure and not recommended

だから私は行ってドキュメントを見ましたが、「ドキュメントはありません」。私はこのコメントを見つけましたが、初期化ベクトルがどうあるべきか、そしてそれをどのように使うべきかについてはまだ言及されていません。誰かが私を啓発できますか?

もう少しGoogleを実行できたはずですが、Stackoverflowが非常に多くの検索結果で最初に表示されるので、この質問はこの問題を抱えている他の人に役立つかもしれないと思いました。

4

1 に答える 1

145

IVは通常、暗号化されたテキストが一意であることを保証する乱数です。

なぜそれが必要なのかを説明するために、キー「secret」で暗号化された人々の名前のデータベースがあり、IVがない場合を考えてみましょう。

1 John dsfa9p8y098hasdf
2 Paul po43pokdfgpo3k4y
3 John dsfa9p8y098hasdf

ジョン1が自分の暗号文(dsfa9p8y098hasdf)を知っていて、他の暗号文にアクセスできる場合、ジョンという名前の他の人を簡単に見つけることができます。

実際には、IVを必要とする暗号化モードでは常にIVが使用されます。IVを指定しない場合、IVは自動的にnullバイトの束に設定されます。最初の例を想像してみてください。ただし、定数IV(00000000)を使用します。

1 John dsfa9p8y098hasdf 00000000
2 Paul po43pokdfgpo3k4y 00000000
3 John dsfa9p8y098hasdf 00000000

暗号化テキストの繰り返しを防ぐために、同じ「秘密」キーとランダムなIVを使用して名前を暗号化できます。

1 John sdf875n90mh28458 45gh3546
2 Paul fg9087n5b60987nf 56897ngq
3 John gjhn0m89456vnler 8907345f

ご覧のとおり、2つの「ジョン」暗号テキストは異なります。各IVは一意であり、暗号化プロセスに影響を与え、最終結果も一意になります。John 1は、ユーザー3の名前が何であるかを認識していません。

もちろん、復号化には、テキストが暗号化されたのと同じIVを使用する必要があります。そのため、テキストをデータベースに保存する必要があります。IVはキーなしでは役に立たないため、暗号化されたテキストとともに送信または保存する必要はありません。

これは非常に単純な例ですが、実際には、IVを使用しないとセキュリティに深刻な影響があります。


これで、コードはIV(1234567812345678)を設定しているように見えますが、復号化には使用していません。それは間違いなく失敗します。

PHPのIV生成関数のいくつかを利用することもできます。私はこれがあなたのために働くはずだと思います:

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$encryptedMessage = openssl_encrypt($textToEncrypt, $encryptionMethod, $secretHash, 0, $iv);
$decryptedMessage = openssl_decrypt($encryptedMessage, $encryptionMethod, $secretHash, 0, $iv);

ストレージ/送信の場合、次のようにIVと暗号文を単純に連結できます。

$data = $iv.$encryptedMessage;

次に、取得時に、復号化のためにIVを引き出します。

$iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
$iv = substr($data, 0, $iv_size);
$decryptedMessage = openssl_decrypt(substr($data, $iv_size), $encryptionMethod, $secretHash, 0, $iv);

詳細については、PHPのMcryptライブラリを確認してください。それは非常に完全な機能を備えており、たくさんの例があり、その多くはopenssh暗号化の実装に役立ちます。 http://php.net/manual/en/function.mcrypt-encrypt.php

于 2012-09-19T00:24:23.817 に答える