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?
-
1You "test" the validity of a key by trying to decrypt something encrypted with it. – Hot Licks Jan 24 '13 at 02:49
-
1You can decrypt something using the wrong key. It wont be the correct decryption but the input text pre encryption is not there to confirm the validity of the decryption. If the input text was there, that would kind of defeat the whole purpose of the process. – Kris Gellci Jan 24 '13 at 02:57
-
2You decrypt something you can recognize. – Hot Licks Jan 24 '13 at 03:08
-
1Please don't post comments or answers about subjects which you do not understand. – Kris Gellci Jan 24 '13 at 03:20
-
Think about it -- the only way to "validate" the key, absent some known text, is to provide some piece of public information that weakens the key. Eg, if you provide a hash of the key, that greatly reduces the number of attempts necessary in a "brute force" attack. – Hot Licks Jan 24 '13 at 03:23
-
1Im doing more than thinking about it, I'm reading about it. You can use a salt to hash a password and then store the resulting key along with the salt on the app side. You can then use the key along with an initialization vector to encrypt the data. The IV and encrypted data can be stored server side from what I understand. You can then use the never stored password in combination with the salt to verify the key the second time around. I just wasn't sure if this was the best way but it sure beats your suggestion. And it is plenty safe by the way. – Kris Gellci Jan 24 '13 at 03:38
-
That made absolutely no sense. – Hot Licks Jan 24 '13 at 03:50
-
2@HotLicks I think it is you that doesn't understand a single thing about encryption. Could you please remove youself from the comments, you are not being constructive in any way. – Maarten Bodewes Jan 24 '13 at 14:33
-
@KrisGellci, your description of a salted hash is good, but feels different from the problem you're describing. Maybe I didn't understand the problem you're actually trying to solve. – Rob Napier Jan 24 '13 at 17:23
3 Answers
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.

- 286,113
- 34
- 456
- 610
-
What do you think about the following process: I use the key to encrypt itself and store that with the rest of the encrypted information. When the user provides a key to decrypt the information, i encrypt the given key with itself and check if it matches the encrypted key. If it does, I can then move forward with decrypting the data using the key provided by the user. – Kris Gellci Jan 24 '13 at 20:55
-
If designed correctly, it could be ok (though without an HMAC, you're still susceptible to manipulation in your ciphertext, so you generally are going to need that anyway). You would definitely want a random IV prior to the key. I don't know if that would be any better than a set of known, fixed bytes at the beginning of the message. I'd have to think about that. – Rob Napier Jan 24 '13 at 21:25
-
Well thanks for the help, I took a look at the RNCryptor class and will probably just use that, it seems to do everything that I want from what I read in its documentation. – Kris Gellci Jan 24 '13 at 21:27
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.

- 3,273
- 16
- 30
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.

- 22,758
- 18
- 92
- 184