JM4
JM4

Reputation: 6798

Issue with PHP mcrypt function

I use the following function to decrypt data on my server:

function decrypt($key, $text) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_ECB, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)));
}

I have read a lot about NOT using ECB however (and know it is deprecated so wanted to switch to CBC. Simply switching the mode to:

function decrypt($key, $text) {
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($text), MCRYPT_MODE_CBC, mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC), MCRYPT_RAND)));
}

does not work however. No errors are generated but the data returned is still encrypted.

What am I missing?

Updated code - still with errors:

$key = "hello"; 

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);

function encrypt($key, $text) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}


function decrypt($key, $text) { 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}


$text = 12345;

echo "Plain Number : " . $text . "<br><br>";

$encrypted = encrypt($key, $text);
echo "AES Number : " . $encrypted . "<br><br>";

echo "Plain Number : ". decrypt($key, $encrypted) . "<br><br>";

this should work - but it returns the error:

blocksize in

blocksize in> Warning: mcrypt_encrypt()

[function.mcrypt-encrypt]: The IV parameter must be as long as the blocksize inblocksize in

blocksize in

Upvotes: 5

Views: 14491

Answers (3)

Stefan Gehrig
Stefan Gehrig

Reputation: 83672

Your updated code has an issue with $iv being a global variable that's not available in the respective en-/decoding functions:

$key = "hello"; 

$iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);

function encrypt($key, $text, $iv) {
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}

function decrypt($key, $text, $iv) { 
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}

$text = 12345;

echo "Plain Number : " . $text . "<br><br>";

$encrypted = encrypt($key, $text, $iv);
echo "AES Number : " . $encrypted . "<br><br>";

echo "Plain Number : ". decrypt($key, $encrypted, $iv) . "<br><br>";

Or you can still rely on the global $iv by importing it into the local function scope:

function encrypt($key, $text) {
    global $iv; // or use $GLOBALS['iv] instead of $iv in the call below
    return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $text, MCRYPT_MODE_CBC, $iv)));
}

function decrypt($key, $text) { 
    global $iv; // or use $GLOBALS['iv] instead of $iv in the call below
    return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, base64_decode($text), MCRYPT_MODE_CBC, $iv));
}

but this is surely not a recommended practice as it couples your code to global variables.

Upvotes: 5

Dan Grossman
Dan Grossman

Reputation: 52372

Did you change the mode when encrypting this text as well?

Also, when using MCRYPT_MODE_CBC, you need to use the same key and IV during encryption and decryption. Randomized IV does not work with CBC.

Upvotes: 3

Cameron Skinner
Cameron Skinner

Reputation: 54516

When you decrypt you need to use the same IV as when you encrypted. It looks like you're generating a new, random IV during decryption.

It's OK to append or prepend the IV to the ciphertext. IVs are not secret but they should be unique for each encrypted message and only used once.

Upvotes: 7

Related Questions