在openssl_encrypt中使用初始化向量

我看了一下这个问题,想自己做。 当我跑这个代码(直接从这个答案 ):

$textToEncrypt = "My super secret information."; $encryptionMethod = "AES-256-CBC"; // AES is used by the US 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 

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

我知道我可以做更多的Googleing,但Stackoverflow出现在如此多的search结果中,我认为这个问题可能对任何有这个问题的人都有用。

IV通常是一个保证encryption文本是唯一的随机数。

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

 1 John dsfa9p8y098hasdf 2 Paul po43pokdfgpo3k4y 3 John dsfa9p8y098hasdf 

如果John 1知道他的密码文本(dsfa9p8y098hasdf)并且可以访问其他密码文本,他可以很容易地find其他人John。

现在实际上,需要一个IV的encryption模式总是使用一个。 如果你不指定一个IV,它会自动设置为一堆空字节。 想象一下第一个例子,但是有一个常量IV(00000000)。

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

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

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

正如你所看到的,这两个“约翰”密码文本现在是不同的。 每个IV都是独一无二的,并且影响了encryption过程,使得最终结果也是独一无二的。 约翰1现在不知道用户3的名字是什么。

解密需要使用相同的文本encryption的IV,这就是为什么它必须存储在数据库中。 如果没有密钥,IV是没有用的,因此传输或存储它与encryption文本是没有关系的。

这是一个过于简单的例子,但事实是,不使用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库。 这是相当全面的function,并有大量的例子,其中许多可以帮助你与opensshencryption实现。 http://php.net/manual/en/function.mcrypt-encrypt.php