Question

I have some code that I am using to encrypt and decrypt some strings in an ios application. The code involves the use of CCCrypt. Is there a reliable way to test the validity of a key used without actually storing the key anywhere? From my research it seems as though the only way to come close to telling if the key is valid is by using key lengths and key hashes. Can anyone guide me in the proper direction for this?

Was it helpful?

Solution

Getting to the answer requires a little bit of background about proper encryption. You may know this already, but most people do this wrong so I'm covering it. (If you're encrypting with a password and don't encode at least an HMAC, two salts, and an IV, you're doing it wrong.)

First, you must use an HMAC (see CCHmac()) any time you encrypt with an unauthenticated mode (such as AES-CBC). Otherwise attackers can modify your ciphertext in ways that cause it to decrypt into a different message. See modaes for an example of this attack. An HMAC is a cryptographically secure hash based on a key.

Second, if your are using password-based encryption, you must use a KDF to convert it into a key. The most common is PBKDF2. You cannot just copy password bytes into a key.

Assuming you're using a password this way, you generally generate two keys, one for encryption and one for HMAC.

OK, with those parts in place, you can verify that the password is correct because the HMAC will fail if it isn't. This is how RNCryptor does it.

There are two problems with this simple approach: you have to process the entire file before you can verify the password, and there is no way to detect file corruption vs bad password.

To fix these issues somewhat, you can add a small block of extra data that you HMAC separately. You then verify that small block rather than the whole file. This is basically how aescrypt does it. Specifically, they generate a "real" key for encrypting the entire file, and then encrypt that key with a PBKDF2-generated key and HMAC that separately. Some forms of corruption still look like bad passwords, but it's a little easier to tell them apart this way.

OTHER TIPS

You can store a known value encrypted with the key in your database. validating if the key is correct is then straightforward: you encrypt the known string, and compare it to the encrypted output in the database. If you stick with a single block of data, then you don't have to worry about modes of operation and you can keep it simple.

It is also possible to store a hash of the key, but I would treat the key as a password, and take all the defensive measures you would take in storing a password in your database (e.g. use bcrypt, salt the hash, etc).

If you can't store these values, you can decrypt something where you don't know the actual contents, but perhaps know some properties of the message (e.g. ASCII text, has today's date somewhere in the string, etc) and test the decrypted message for those properties. Then if the decrypted block that doesn't have those properties (e.g. has bytes with MSB set, no instance of the date), you know the key is invalid. There is a possibility of a false positive in this case, but chances are very low.

Generally I agree with Peter Elliott. However, I have couple of additional comments:

a) If keys were randomly generated then storing hashes of the keys are safe

b) You can always attach to encrypted message (if you can control that) a hash of orginial message. In such case, you can decrypt message, get hash of decrypted message and compare it with the hash of original message. If they are eqaul then correct key was used for decryption.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top