hash — извлекает ключ и IV из строки для шифрования AES в CryptoJS и переполнения стека

Как я могу сгенерировать ключ и IV каждый из общей строки, чтобы они могли служить в алгоритме шифрования с использованием AES в PHP?

Пример:

$key_string = derivate_in_valid_key("i love stackoverflow");
$iv_string = derivate__in_valid_iv("i love questions");

и таким образом, что я могу повторить процесс деривации в JavaScript также.

1

Решение

Вы можете использовать PBKDF2 для получения ключа и IV из пароля. CryptoJS а также PHP оба обеспечивают их реализацию.

AES поддерживает размеры ключей 128, 192 и 256 бит, а размер блока 128 бит. Размер IV должен совпадать с размером блока для таких режимов, как CBC.

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

JavaScript (DEMO):

var password = "test";

var iterations = 500;
var keySize = 256;
var salt = CryptoJS.lib.WordArray.random(128/8);

console.log(salt.toString(CryptoJS.enc.Base64));

var output = CryptoJS.PBKDF2(password, salt, {
keySize: keySize/32,
iterations: iterations
});

console.log(output.toString(CryptoJS.enc.Base64));

пример вывода:

CgxEDCi5z4ju1ycmKRh6aw ==
7G3 + NUWtbOooVeTDyLqMaDgnqCkiQCjZi3wnspRPabU =

PHP:

$password = "test";
$expected = "7G3+NUWtbOooVeTDyLqMaDgnqCkiQCjZi3wnspRPabU=";

$salt = 'CgxEDCi5z4ju1ycmKRh6aw==';
$hasher = "sha1"; // CryptoJS uses SHA1 by default
$iterations = 500;
$outsize = 256;

$out = hash_pbkdf2($hasher, $password, base64_decode($salt), $iterations, $outsize/8, true);

echo "expected: ".$expected."\ngot:      ".base64_encode($out);

выход:

ожидается: 7G3 + NUWtbOooVeTDyLqMaDgnqCkiQCjZi3wnspRPabU =
получил: 7G3 + NUWtbOooVeTDyLqMaDgnqCkiQCjZi3wnspRPabU =

Предыдущий раздел немного неуклюжий, потому что нужно создать две соли и сделать два вызова PBKDF2. PBKDF2 поддерживает переменный вывод, поэтому можно просто использовать одну соль, запросить вывод размера ключа плюс размер iv и отрезать их. Следующий код делает это, поэтому только одна соль должна быть отправлена ​​вместе с зашифрованным текстом.

JavaScript (DEMO):

var password = "test";

var iterations = 1000;
// sizes must be a multiple of 32
var keySize = 256;
var ivSize = 128;
var salt = CryptoJS.lib.WordArray.random(128/8);

console.log(salt.toString(CryptoJS.enc.Base64));

var output = CryptoJS.PBKDF2(password, salt, {
keySize: (keySize+ivSize)/32,
iterations: iterations
});

// the underlying words arrays might have more content than was asked: remove insignificant words
output.clamp();

// split key and IV
var key = CryptoJS.lib.WordArray.create(output.words.slice(0, keySize/32));
var iv = CryptoJS.lib.WordArray.create(output.words.slice(keySize/32));

console.log(key.toString(CryptoJS.enc.Base64));
console.log(iv.toString(CryptoJS.enc.Base64));

пример вывода:

0Iulef2TncciKGmdwvQX3Q ==
QeTc3zHuG3JcdtOCkzU2uJWTnrMEggvF1dNUbgNMyzg =
L1YNlFe54 + Cvepp / pXsHtg ==

PHP:

$password = "test";
$expectedKey = "QeTc3zHuG3JcdtOCkzU2uJWTnrMEggvF1dNUbgNMyzg=";
$expectedIV = "L1YNlFe54+Cvepp/pXsHtg==";

$salt = '0Iulef2TncciKGmdwvQX3Q==';
$hasher = "sha1";
$iterations = 1000;
$keysize = 256;
$ivsize = 128;

$out = hash_pbkdf2($hasher, $password, base64_decode($salt), $iterations, ($keysize+$ivsize)/8, true);

// split key and IV
$key = substr($out, 0, $keysize/8);
$iv = substr($out, $keysize/8, $ivsize/8);

// print for demonstration purposes
echo "expected key: ".$expectedKey."\ngot:          ".base64_encode($key);
echo "\nexpected iv: ".$expectedIV."\ngot:         ".base64_encode($iv);

выход:

ожидаемый ключ: QeTc3zHuG3JcdtOCkzU2uJWTnrMEggvF1dNUbgNMyzg =
получил: QeTc3zHuG3JcdtOCkzU2uJWTnrMEggvF1dNUbgNMyzg =
ожидается, iv: L1YNlFe54 + Cvepp / pXsHtg ==
получил: L1YNlFe54 + Cvepp / pXsHtg ==

CryptoJS по умолчанию использует SHA1, так что вы можете использовать другую хеш-функцию, передав хеш-функцию в качестве hasher свойство объекта. Вы также должны, вероятно, использовать более высокий счетчик итераций.

У меня нет версии PHP 5.5+, поэтому я использовал реализацию PBKDF2 из Вот.

9

Другие решения

Других решений пока нет …