0

I've found a pair of encryption and decryption functions that look like they obey all the rules of data security that I'm desperate to fully understand but probably won't be able to without a doctorate in this stuff.

They work great when I'm encrypting and decrypting something on the same page with the same IV.

But when I try saving the results to an SQL database and then pulling them back out again and decrypting, it doesn't work.

$key = "secretsecret";

$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 = "the text to encrypt";

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

$encrypted = encrypt($key, $text, $iv);

echo "Encrypted Text: " . $encrypted . "<br><br>";

echo "Decrypted Text: ". decrypt($key, $encrypted, $iv) . "<br><br>"; //this works fine

//save encrypted text to SQL
mysql_query("UPDATE table SET test='".addslashes($encrypted)."' WHERE id='1'");

Then if on another page view I pull the text back out and try to:

echo "Decrypted Text: ". decrypt($key, $textFromSQL, $iv) . "<br><br>";

I get gibberish. What do I need to do to get the text decrypted properly with a different IV?

rgbflawed
  • 1,957
  • 1
  • 22
  • 28

1 Answers1

3

You need to use the same Initialization Vector (IV) in the decryption as you do in the enryption. This means you need to store the IV in the database.

The IV doesn't need to be secret, unlike the key.

Something like this:

mysql_query("UPDATE table SET test='".addslashes($encrypted)."', IV='".addslashes($IV)."' WHERE id='1'");

Then when you decrypt the data use the stored IV.

Sani Huttunen
  • 23,620
  • 6
  • 72
  • 79
  • That suggests to me that the mcrypt_decrypt function doesn't need the $iv at all. That all I would need to do is decrypt and lop off the first [length of iv] characters. (this taking the storing the IV joined with the text method instead of putting in separate columns) So if this is the case, why is PHP giving me warnings when I try and remove $iv from the mcrypt_decrypt function? – rgbflawed Mar 14 '14 at 20:41
  • Because you are using CBC (Cipher Block Chaining) mode. CBC requires an IV. ECB (Electronic Code Book) mode does not require an IV. – Sani Huttunen Mar 14 '14 at 20:42
  • This is very very helpful! Any chance you can tell me why any mode would require an IV if it's not actually used in the decryption? – rgbflawed Mar 14 '14 at 20:44
  • 1
    The IV is used in CBC. You can provide an IV in EBC mode but it's not used and would be pointless. Any mode requiring an IV uses the IV. See [this](http://stackoverflow.com/questions/12522191/c-sharp-tripledes-provider-without-an-initialization-vector/12522385#12522385]) answer I gave to another question. – Sani Huttunen Mar 14 '14 at 20:45
  • That accurately describes why you'd need it for encryption. But why do you need an IV for *decryption*? – rgbflawed Mar 14 '14 at 20:47
  • You still need to have the same "starting point" in both the encryption and decryption. The IV is the "starting point". You can see it as a seed value much like you would use in a PRNG. – Sani Huttunen Mar 14 '14 at 20:48
  • Okay so we're again at "the same"... which means even with CBC you have to save that specific IV so that specific string can be decrypted again later? I think I've got it! Thanks Sani!!! – rgbflawed Mar 14 '14 at 20:49
  • FYI: Never ever ever use ECB mode for real data - it reveals patterns in your data that repeat over blocks. – Anti-weakpasswords Mar 15 '14 at 02:43
  • @Anti-weakpasswords: That really depends on the size of the data. Granted that ECB is not desired but it still has its uses. – Sani Huttunen Mar 15 '14 at 02:45