Что такое 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".