3

Here's a theoretical one that not only applies to PHP, but probably to more languages.

Let's say that I encrypt a string with the mcrypt library using and the AES-256 cipher. The string, encrypted, would now look similar to þøÆ{”ò(ü´îÚÜÇW¹ËŸK­¯L‘rø?ª¶!JF£­º+Œ’Ú'‚.

If the encryption key would change between the events of decryption and encryption, the result of the decryption would obviously be worthless.
Since an encrypted string contains, at least to me, random chars, It wouldn't be easy to run some sort of test on it to ensure that it is in encrypted/decrypted state.

I've spent some time thinking. How can I test that a string has been properly decrypted?
What if I appended a small prefix to the original string before encrypting it in the first place, and then removed this prefix upon decryption. If this prefix wasn't found, it would be safe to say that the decryption has failed.

Would this be an appropriate way to handle this?

Industrial
  • 41,400
  • 69
  • 194
  • 289
  • 9
    You could include a hash(such as sha-1) of your plaintext instead of a simple prefix. That way you get integrity checking as a bonus. – CodesInChaos Feb 22 '11 at 19:03
  • @Code that's a great idea. The hash would have to be followed by a defined character to mark the boundary – Pekka Feb 22 '11 at 19:09
  • Regarding your method it is safe if you can find a string $a such that for each possible string $b, the encoding of $a . $b will never begin with $a. – greg0ire Feb 22 '11 at 19:09
  • Why would you need a defined character? A typical hash has constant size. For example a sha-1 hash is only 20 bytes. – CodesInChaos Feb 22 '11 at 19:10
  • @CodeInChaos That's a great idea, if the encrypted string is of considerable size or even a file/document. I am doubtful that it would be a good idea to implement on small strings though – Industrial Feb 22 '11 at 19:12
  • If the strings are short, you could use a short hash such as CRC32. – CodesInChaos Feb 22 '11 at 19:26

2 Answers2

3

To test data integrity you want a Message Authentication Code (MAC).

There are a few stand-alone MAC algorithms, which look like a hash function with a key. The very standard MAC algorithm is HMAC (which uses a hash function).

Since you also encrypt the data, you will want to use an encryption mode with a builtin MAC; there are a few such modes, such as GCM or EAX. Those modes apply to a block cipher, usually the AES.

Adding a known prefix or suffix to the data before encryption is a homemade MAC. MACs are subtle and error prone. For instance, if you add a CRC32 and then encrypt with a stream cipher (or a block cipher in CTR mode), then you are reproducing one of the seven capital sins of WEP (see section 4 in particular, for the CRC32-as-MAC issue). Basically your integrity check is no longer resistant to active attacks; you are only detecting innocent mistakes, such as using the wrong key.

(Unfortunately, it seems that MCrypt does not support any combined encryption/MAC mode. PHP itself, when compiled with the --with-mhash option, provides the mhash() function which implements both raw hashing, and HMAC.)

Community
  • 1
  • 1
Thomas Pornin
  • 72,986
  • 14
  • 147
  • 189
  • Hi Thomas. Thanks for an extensive answer. It will take some time for me to digest it! Regarding the `mhash()` function in PHP - it has been replaced by `hash()` and in this case(?) `hash_hmac` http://www.php.net/manual/en/function.hash-hmac.php – Industrial Feb 23 '11 at 08:25
  • Just a quickie: Why are MAC's subtle and error prone, as you say? – Industrial Feb 23 '11 at 16:35
  • 1
    @Industrial: the conceptual reason is that being a secure hash function does not mean that the function is a proper random oracle emulation. In simpler words, the security of a MAC relies on precise security characteristics which you do not necessarily get from a hahs function, even if the hash function is, by itself, considered as "safe", which means "collision-resistant". Homemade MACs are often weak (but not _obviously_ weak). HMAC is a structure where the underlying hash function is called twice in a way which allowed some clever researchers to actually _prove_ that it is secure as a MAC. – Thomas Pornin Feb 23 '11 at 20:06
1

How can I test that a string has been properly decrypted?

The "small prefix" idea should be fine; also the excellent idea by @CodeInChaos. Other than that, storing the string in some defined format (like serialize() or json_encode()) and failing to restore it (unserialize(), json_decode()) would be indication of a broken decryption as well.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 1
    makes me curious as to the likelihood of two different keys on one crypted string producing two completely different, yet still valid, JSON/serialize plaintexts. – Marc B Feb 22 '11 at 19:17