0

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();

I get a fine looking 64 characters long string, which I send to my server.

On my server (running CodeIgniter 3) I am using the CI encryption library and I'm loading it as required, but when I try to decrypt the string like so:

$this->encryption->decrypt($this->input->post('encUser'), array(
    'cipher' => 'aes-128',
    'mode' => 'cbc',
    'hmac' => FALSE,
    'key' => $key
));

the function returns (bool)false, meaning something went wrong.

What am I doing wrong?

Note: not sure how much I need to encrypt with iv because the CI library just uses the first 16 chars from the string itself.

** EDIT **

I'm creating my $kay (passphrase) with the help of the random_int polyfill and this is my function:

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;
}

Which i am calling random_str(32);

Example generated key: 1xB8oBQgXGPhcKoD0QkP1Uj4CRZ7Sy1c

** UPDATE ** thanks to Artjom.B's answer(and chat :) ) we got it working, using his answer's client side code and fixing the server side code to be:

$user = $this->encryption->decrypt(base64_decode($this->input->post('encUser')), array(
        'cipher' => 'aes-256',
        'mode' => 'cbc',
        'hmac' => FALSE,
        'key' => $key
    ));

and now everything is working.

FireBrand
  • 463
  • 5
  • 16

1 Answers1

0

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_BytesToKey).

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.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Useing `base64_decode()` on the encrypted username gave me this:`�%؋{���?{!� ����i�v�w���Kse��2X�c�;��*A;` and the decrypt function returned `false` again – FireBrand Jun 05 '16 at 13:18
  • 1
    Have you encoded the `$key` to Hex for JavaScript, but used the raw `$key` for decryption? – Artjom B. Jun 05 '16 at 13:24
  • I used it raw, I tried to parse it now but i'm not able to parse it correctly on the server for some reason – FireBrand Jun 05 '16 at 13:40
  • Can you show how your key (example) looks and how you've created it? – Artjom B. Jun 05 '16 at 13:43
  • key example: `1xB8oBQgXGPhcKoD0QkP1Uj4CRZ7Sy1c` – FireBrand Jun 05 '16 at 13:46
  • 1
    There is something wrong with how you're generating the key. You've requested 16 bytes, but you've presented a key with 32 bytes. So, you're using AES-256 and not AES-128. So you should change the `'cipher'`. I've also made an edit to include correct key encoding at the JavaScript side. – Artjom B. Jun 05 '16 at 14:16
  • My bad, i am requesting a 32 bytes key, iv'e edited that in my question now. is the `base64_decode()` still needed for the encrypted username? – FireBrand Jun 05 '16 at 14:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113848/discussion-between-firebrand-and-artjom-b). – FireBrand Jun 05 '16 at 14:31