Использование вектора инициализации в шифровании 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 ответов


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

чтобы предотвратить повторные тексты шифров, мы можем зашифровать имена, используя тот же "секретный" ключ и random 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