Я пытаюсь зашифровать имя пользователя, отправленное с помощью запроса POST на мой сервер (написано в Codeigniter 3), поэтому я шифрую на стороне клиента с помощью CryptoJS вот так:
var user = $('.user').val();
var key = "<? echo($key);?>"; //$key is created on the server side
var encUser = CryptoJS.AES.encrypt(user, key, {
mode: CryptoJS.mode.CBC
}).toString();
Я получаю строку длиной 64 символа, которая отправляется на мой сервер.
На моем сервере (работает CodeIgniter 3) я использую CI шифрование библиотека и я загружаю его как требуется, но когда я пытаюсь расшифровать строку, например, так:
$this->encryption->decrypt($this->input->post('encUser'), array(
'cipher' => 'aes-128',
'mode' => 'cbc',
'hmac' => FALSE,
'key' => $key
));
функция возвращает (bool)false
, значит что-то пошло не так.
Что я делаю неправильно?
Примечание: не уверен, сколько мне нужно шифровать с iv
потому что библиотека CI просто использует первые 16 символов из самой строки.
** РЕДАКТИРОВАТЬ **
Я создаю свой $kay
(фраза) с помощью random_int polyfill и это моя функция:
private function random_str($length, $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
{
$str = '';
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < $length; ++$i) {
$str .= $keyspace[random_int(0, $max)];
}
return $str;
}
Который я звоню random_str(32)
;
Пример сгенерированного ключа: 1xB8oBQgXGPhcKoD0QkP1Uj4CRZ7Sy1c
** ОБНОВИТЬ **
благодаря ответу Artjom.B (и чат :)
) мы получили его, используя клиентский код его ответа и исправив код на стороне сервера так:
$user = $this->encryption->decrypt(base64_decode($this->input->post('encUser')), array(
'cipher' => 'aes-256',
'mode' => 'cbc',
'hmac' => FALSE,
'key' => $key
));
и теперь все работает.
В CryptoJS, если key
является строкой, то будет предполагать, что key
на самом деле пароль, генерирует случайную соль и получает фактический ключ и IV из пароля + соли (это делается в OpenSSL-совместимом способе через EVP_BytesToKey
).
Библиотека шифрования CodeIgniter не поддерживает этот тип получения ключей. Вам придется либо изменить свой код CryptoJS, чтобы передать проанализированный WordArray
:
var key = CryptoJS.enc.Hex.parse("<? echo(bin2hex($key));?>");
var iv = CryptoJS.lib.WordArray.random(128/8);
var encUser = CryptoJS.AES.encrypt(user, key, {
iv: iv
}).ciphertext;
return iv.concat(encUser).toString(CryptoJS.enc.Base64);
Поскольку IV написан перед зашифрованным текстом, CodeIgniter должен правильно его прочитать, и его не нужно указывать явно. Удостоверься что key
правильно закодирован как Hex или Base64, потому что двоичное кодирование не работает правильно в JavaScript. Также на стороне PHP зашифрованный текст должен быть декодирован из Base64.
Вы также можете реализовать EVP_BytesToKey
в PHP, как я показал Вот.
Других решений пока нет …