php openssl_encrypt中初始化向量的使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11821195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 02:12:23  来源:igfitidea点击:

Use of Initialization Vector in openssl_encrypt

phpsecurityopenssl

提问by Alfo

I had a look at thisquestion, and wanted to do it for myself. When I ran this code (taken straight from this answer):

我看了一下这个问题,并想为自己做。当我运行此代码时(直接取自此答案):

$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";

However I get the warning

但是我收到警告

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

So I went and had a look at the docs, but there 'is no documentation'. I found this comment, but still no mention of what the Initialization Vector should be and how I should use it. Can anyone enlighten me?

所以我去看了看文档,但“没有文档”。我找到了这个评论,但仍然没有提到初始化向量应该是什么以及我应该如何使用它。任何人都可以启发我吗?

I know I could have done some more Googleing, but Stackoverflow comes up first in so many search results I thought this question might be useful to anyone else who was having this problem.

我知道我可以做更多的谷歌搜索,但是 Stackoverflow 在如此多的搜索结果中首先出现,我认为这个问题可能对遇到此问题的其他人有用。

回答by Joel Mellon

An IV is generally a random number that guarantees the encrypted text is unique.

IV 通常是一个随机数,可保证加密文本是唯一的。

To explain why it's needed, let's pretend we have a database of people's names encrypted with the key 'secret' and no IV.

为了解释为什么需要它,让我们假设我们有一个用密钥“秘密”加密的人名数据库,没有 IV。

1 John dsfa9p8y098hasdf
2 Paul po43pokdfgpo3k4y
3 John dsfa9p8y098hasdf

If John 1 knows his cipher text (dsfa9p8y098hasdf) and has access to the other cipher texts, he can easily find other people named John.

如果 John 1 知道他的密文 (dsfa9p8y098hasdf) 并且可以访问其他密文,他就可以轻松找到其他名为 John 的人。

Now in actuality, an encryption mode that requires an IV will always use one. If you don't specify an IV, it's automatically set to a bunch of null bytes. Imagine the first example but with a constant IV (00000000).

现在实际上,需要 IV 的加密模式将始终使用 IV。如果您不指定 IV,它会自动设置为一堆空字节。想象一下第一个示例,但具有恒定的 IV (00000000)。

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

To prevent repeated cipher texts, we can encrypt the names using the same 'secret' key and random IV's:

为了防止重复的密文,我们可以使用相同的“秘密”密钥和随机 IV 来加密名称:

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

As you can see, the two 'John' cipher texts are now different. Each IV is unique and has influenced the encryption process making the end result unique as well. John 1 now has no idea what user 3's name is.

如您所见,两个“约翰”密文现在不同了。每个 IV 都是独一无二的,并且影响了加密过程,从而使最终结果也是独一无二的。John 1 现在不知道用户 3 的名字是什么。

Decryption requires the use of the same IV the text was encrypted with of course, which is why it must be stored in the database. The IV is of no use without the key so transmitting or storing it with the encrypted text is of no concern.

解密需要使用与加密文本相同的 IV,这就是为什么它必须存储在数据库中的原因。没有密钥,IV 就没有用处,因此与加密文本一起传输或存储它是无关紧要的。

This is an overly simplistic example, but the truth is, not using IV's has serious security ramifications.

这是一个过于简单的例子,但事实是,不使用 IV 会产生严重的安全后果。



Now your code appears to be setting the IV (1234567812345678) but not using it on decryption. That's certain to fail.

现在您的代码似乎正在设置 IV (1234567812345678) 但没有在解密时使用它。那肯定会失败。

You also may want to utilize some of PHP's IV generation functions. I think this should work for you:

您可能还想使用一些 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);

For storage/transmission, you can simply concatenate the IV and cipher text like so:

对于存储/传输,您可以简单地连接 IV 和密文,如下所示:

$data = $iv.$encryptedMessage;

Then on retrieval, pull the IV out for decryption:

然后在检索时,拉出 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);


For more info, check out PHP's Mcrypt library. It's quite full featured and has tons of examples, many of which can help you out with openssh encryption implementations. http://php.net/manual/en/function.mcrypt-encrypt.php

有关更多信息,请查看 PHP 的 Mcrypt 库。它功能齐全,有大量示例,其中许多可以帮助您实现 openssh 加密。 http://php.net/manual/en/function.mcrypt-encrypt.php