Что такое openssl iv, и зачем мне нужен ключ и iv?
Я собираюсь использовать следующий скрипт для шифрования и дешифрования данных. Я использую его, потому что мое текущее шифрование не работает на нашем новом сервере. В настоящее время мы используем mcrypt, поэтому я хочу перейти на openssl.
в нашей базе данных мы используем шифрование aes, которое использует 128-битный ключ, поэтому я знаю, что такое ключ, но я не знаю, что такое openssl iv? И зачем мне ключ и капельница?--2-->
код, который я собираюсь использовать, это то, что я нашел на веб-сайте, потому что я не очень хорошо понимаю шифрование.
очевидно, я изменю его так, чтобы ключ хранился где-то еще.
function encrypt_decrypt($action, $string) {
$output = false;
$encrypt_method = "AES-256-CBC";
$secret_key = 'This is my secret key';
$secret_iv = 'This is my secret iv';
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
else if( $action == 'decrypt' ){
$output = openssl_decrypt(base64_decode($string), $encrypt_method, $key, 0, $iv);
}
return $output;
}
$plain_txt = "This is my plain text";
echo "Plain Text = $plain_txtn";
$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txtn";
$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txtn";
if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";
echo "n";
2 ответов
вектор инициализации является частью того, что делает AES в режиме работы CBC (Cipher Block Chaining) - IVs не уникальны для OpenSSL. CBC работает путем XORing предыдущего блока с текущим блоком. Самый первый блок не имеет предыдущего блока, поэтому IV служит этой цели.
Почему это необходимо, требует немного понимания того, как работают блочные шифры. Без этой цепочки и IV мы остаемся с режимом AES, называемым ЕЦБ, или электронной кодовой книгой. У ЕЦБ есть слабые места, которые позволяют выбранная атака открытым текстом, среди многих других проблем.
Я бы рекомендовал потратить немного времени с лучшими практиками для векторов инициализации CBC. Неправильное их использование может ослабить общую безопасность AES. Краткое объяснение:
- IVs должны быть случайными и генерироваться CSPRNG.
- IVs не следует повторно использовать. То есть не шифруйте открытый текст "A" и открытый текст "B" с тем же IV. Каждая запись должна иметь свой IV.
- в IV-это не секрет, как ключ. Он может храниться в виде открытого текста вместе с зашифрованным текстом.
также имейте в виду, что этот совет применяется только к AES-CBC. Если вы когда-либо исследовали другие режимы AES, такие как GCM, это не применяется.
Я думаю, что вы, возможно, перепутали "хэшированный ключ" и " iv " (Бог знает, что я сделал при запуске crypto). хэшированный ключ-это именно то, что вы сделали. Для iv вы должны использовать разные случайные данные каждый раз, когда шифрование выполняется с одним и тем же ключом. (мой фон: мне пришлось создать обработчик защищенного сеанса pdo, который шифрует / расшифровывает данные сеанса, поэтому я закончил реализацию AES-256-CBC с помощью расширения openssl)
просто небольшой совет, если кто попадет сюда.
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
это не правильный способ генерация iv + нет необходимости в secret_iv, потому что iv должен быть случайным, как он получает. Не относитесь к нему (или не понимаете его) так же, как к хешированию.
поскольку у вас есть доступ к расширению openssl, есть лучший / безопасный способ генерации iv для выбранного шифра, openssl также может сказать вам правильную длину iv для шифра:
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length('AES-256-CBC'));
Он будет в двоичном формате, поэтому, если вам это нужно в hex, используйте bin2hex ($iv). Если вам нужно сохранить сгенерированный iv в mysql, я храню его в raw формат (тип поля varbinary, двоичный тоже работает).
еще одна вещь. У вас есть тег $options, установленный в 0 как в openssl_encrypt, так и в _decrypt, что означает, что "если установлено значение true, будет возвращено как исходные данные, иначе возвращаемое значение будет закодировано base64".