I'm trying to encrypt a username sent via POST request to my server (written in Codeigniter 3), so I'm encrypting on the client side with CryptoJS like so:
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();
$this->encryption->decrypt($this->input->post('encUser'), array(
'cipher' => 'aes-128',
'mode' => 'cbc',
'hmac' => FALSE,
'key' => $key
));
(bool)false
iv
$kay
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
:)
$user = $this->encryption->decrypt(base64_decode($this->input->post('encUser')), array(
'cipher' => 'aes-256',
'mode' => 'cbc',
'hmac' => FALSE,
'key' => $key
));
In CryptoJS, if key
is a string, then it will assume that key
is actually a password, generate a random salt and derive the actual key and IV from password+salt (this is done in an OpenSSL-compatible way through EVP_ByteToKey
).
CodeIgniter's Encryption library doesn't support this type of key derivation. You will either have to change your CryptoJS code to pass in a parsed 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);
Since the IV is written in front of the ciphertext, CodeIgniter should read it correctly and it doesn't have to be specified explicitly. Make sure that key
is correctly encoded as Hex or Base64, because binary encoding doesn't work in JavaScript correctly. Also, at the PHP side, the ciphertext must be decoded from Base64.
You could also implement EVP_BytesToKey
in PHP as I've shown here.