Использование вектора инициализации в шифровании openssl


Я взглянул на этот вопрос, и хотел сделать это для себя. Когда я запустил этот код (взятый прямо из этого ответа):

$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

поэтому я пошел и посмотрел на docs, но там нет документации'. Я нашел это комментарий, но до сих пор нет упоминания о том, что вектор инициализации должен быть и как я должен использовать его. Может кто-нибудь просветить меня?

Я знаю, что я мог бы сделать некоторые больше Googleing, но Stackoverflow появляется первым во многих результатах поиска, я думал, что этот вопрос может быть полезен для всех, у кого была эта проблема.

1 62

1 ответ:

IV, как правило, случайное число, которое гарантирует, что зашифрованный текст уникален.

чтобы объяснить, зачем это нужно, давайте представим, что у нас есть база данных имен людей, зашифрованных ключом "секрет" и нет IV.

1 John dsfa9p8y098hasdf
2 Paul po43pokdfgpo3k4y
3 John dsfa9p8y098hasdf

если Джон 1 знает свой шифрованный текст (dsfa9p8y098hasdf) и имеет доступ к другим шифрованным текстам, он может легко найти других людей по имени Джон.

теперь на самом деле, режим шифрования, который требует IV всегда будет использовать один. Если вы не указывайте IV, он автоматически устанавливается в кучу нулевых байтов. Представьте себе первый пример, но с константой 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

как вы можете видеть, два зашифрованных текста "Джон" теперь разные. Каждый IV уникален и повлиял на процесс шифрования, что делает конечный результат уникальным. Джон 1 теперь понятия не имеет, как зовут пользователя 3 есть.

расшифровка требует использования того же IV текст был зашифрован, конечно, поэтому он должен храниться в базе данных. IV не имеет смысла без ключа, поэтому передача или хранение его с зашифрованным текстом не имеет никакого значения.

это слишком упрощенный пример, но правда в том, что не использование IV имеет серьезные последствия для безопасности.


теперь ваш код, похоже, устанавливает IV (1234567812345678), но не использует его расшифровка. Это наверняка провалится.

вы также можете использовать некоторые из функций IV поколения PHP. Я думаю, что это должно работать для вас:

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

для получения дополнительной информации, проверьте библиотеку Mcrypt PHP. Он довольно полнофункциональный и имеет множество примеров, многие из которых могут помогите вам с реализацией шифрования openssh. http://php.net/manual/en/function.mcrypt-encrypt.php