5

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

2
  • 1
    Is the return data the same as what you passed in? If it is, then something's wrong with the decryption function. Otherwise it's working normally, and you've just used the wrong key/IV, and gotten garbage back out. Commented Nov 10, 2010 at 22:22
  • @Marc B - yes, in fact I am running the encryption and decryption on the same page even to make sure info is good but I get errors. I am going to try and see some of the suggestions below make a difference. Commented Nov 10, 2010 at 22:38

3 Answers 3

7

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.

Sign up to request clarification or add additional context in comments.

7 Comments

@cameron - thanks for the help - i'll have to look back into IVs but in reality - what is the overall purpose of an IV if you are already using a key to encrypt the file to begin with (likely your IV is stored in the same location as the data itself which isn't very safe if your server is compromised.
The IV is just there to prevent statistical cryptanalysis techniques. It's not a secret so it doesn't matter if it's disclosed. Using a random IV for each message means that if you encrypt the same message twice with the same key you get different ciphertexts. That means an eavesdropper cannot look for patterns in a sequence of messages, even if they know the IV for each message. This is important even if you're not encrypting the same message repeatedly.
@cameron - there is a new edit above which still gives errors even when on the same page.
Hmm. Not sure. Try checking that mcrypt_get_iv_size returns the right number and that mcrypt_create_iv actually generates an IV of the right length. It could be that one is reported in bits and the other in bytes.
$size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC); returns 16
|
5

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.

3 Comments

mcrypt_create_iv eliminates the warning, but it seems to be horribly slow for some reason.
Not sure why, but on my Linux systems using MCRYPT_DEV_RANDOM for the call to mcrypt_create_iv took a good minute. Using MCRYPT_DEV_URANDOM though is practically instant as one would expect.
No doubt you notice this specifically on VM's. This is due to VM's not having a decent source of entropy for /dev/random.
3

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.

3 Comments

i did change the encrypt mode as well; however, to your last point the 'randomized IV' not working - sample code on php.net seems to state otherwise (although it does use tripledes as cipher) : php.net/manual/en/function.mcrypt-cbc.php
I think @Dan was saying that you can't decrypt with any old random IV, it must be the same as was used for encryption. ECB doesn't use an IV.
Note that the IV for the ECB mode is zero, so the IV created for ECB is an empty string. For any other mode, the IV length is greater than zero.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.