Что такое openssl iv и зачем мне нужны ключ и капельница?


Я собираюсь использовать следующий скрипт для шифрования и дешифрования некоторых данных. Я использую его, потому что мое текущее шифрование не работает на нашем новом сервере. В настоящее время мы используем mcrypt, поэтому я хочу перейти на openssl.

В нашей базе данных мы используем шифрование aes, в котором используется 128-битный ключ, поэтому я знаю, что такое ключ, но я не знаю, что такое openssl iv? И зачем мне понадобятся ключ и капельница.

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

Очевидно, я изменю его так, чтобы ключ хранился где-то в другом месте.

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_txt\n";

$encrypted_txt = encrypt_decrypt('encrypt', $plain_txt);
echo "Encrypted Text = $encrypted_txt\n";

$decrypted_txt = encrypt_decrypt('decrypt', $encrypted_txt);
echo "Decrypted Text = $decrypted_txt\n";

if( $plain_txt === $decrypted_txt ) echo "SUCCESS";
else echo "FAILED";

echo "\n";
Author: Artjom B., 2016-09-09

2 answers

Вектор инициализации является частью того, что обеспечивает работу AES в режиме CBC (цепочка блоков шифрования) - IV не являются уникальными для OpenSSL. CBC работает, связывая предыдущий блок с текущим блоком. Самый первый блок не имеет предыдущего блока, поэтому IV служит этой цели.

Почему это необходимо, требует некоторого понимания того, как работают блочные шифры. Без этой цепочки и IV мы остаемся с режимом AES, называемым ECB, или Электронной кодовой книгой. У ЕЦБ есть слабые стороны, которые позволяют выбранная атака открытым текстом, среди многих других проблем.

Я бы рекомендовал потратить немного времени на изучение лучших практик для векторов инициализации CBC. Неправильное их использование может ослабить общую безопасность AES. Краткое объяснение таково:

  • IV должны быть случайными и генерироваться CSPRNG.
  • Капельницы не следует использовать повторно. То есть не шифруйте открытый текст "A" и открытый текст "B" с помощью одного и того же IV. Каждая запись должна иметь свой собственный IV.
  • Капельница не является секретом, как ключ. Он может храниться в виде открытого текста вместе с зашифрованным текстом.

Также имейте в виду, что этот совет применим только к AES-CBC. Если вы когда-либо изучали другие режимы AES, такие как GCM, это не применимо.

 9
Author: vcsjones, 2016-09-09 13:56:41

Я думаю, что вы, возможно, перепутали "хэшированный ключ" и "iv" (Бог знает, что я сделал, когда начинал криптографию). хэшированный ключ - это именно то, что вы сделали. Для 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'));

Он будет в двоичном формате, поэтому, если он вам нужен в шестнадцатеричном формате, используйте bin2hex($iv). Если вам нужно сохранить сгенерированный iv в mysql, я сохраняю его в формате raw (тип поля varbinary, двоичный файл также работает).

Еще одна вещь. У вас есть тег $options, установленный в 0 как в openssl_encrypt, так и в _decrypt, что означает "если установлено значение true, будут возвращены необработанные выходные данные, в противном случае возвращаемое значение будет закодировано в кодировке base64".

 2
Author: ConfusedAmish, 2017-05-23 19:56:41