Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

I have a program which uses AES-256 in CBC mode to encrypt and decrypt files. As I have quickly realized, AES will even use an incorrect passphrase to decrypt data, which leaves me with no way to validate whether the passphrase was correct or not and, in turn, whether I'm decrypting things successfully.

One idea which was suggested before was to embed a known value in beginning of the encrypted data to validate whether decryption produced an expected result. Essentially, since the IV is a known value, I thought of simply hashing it and embedding it as the first 32 bytes in the file. If, after the first block is decrypted, the first 32 bytes equal the hash of the IV, we can know that decryption succeeded. If not, we can know that it failed.

Does this in any way compromise my encrypted files?

share|improve this question
2  
I'd use a MAC instead. For example use HMAC-SHA-2 on the ciphertext. Derive the MAC key and the AES key from a master key. –  CodesInChaos Feb 20 '13 at 22:36
1  

2 Answers 2

That would work and almost certainly wouldn't have any negative impact on security, but it would be cleaner just to have a string of 16 0x00 bytes at the start of a message, instead. Not only does this save you the trouble of hashing, but you stay within the standard threat model for CBC which assumes the IV is independent of the message blocks. (One can come up with pathological yet technically still secure hash functions that would cause your approach to become insecure.)

And a quick note: the block size is 16 bytes, not 32 bytes. The 256 in AES-256 refers to the length of the key, not the block.

You should look into using a message authentication code, such as HMAC. Doing so will not only validate a correct passphrase, but will also ensure the ciphertext has not been tampered with. (CBC will prevent someone from learning information about the plaintext, but will not stop someone who already knows it from tampering with the ciphertext so that parts of it decrypt to strings of his choosing.)

Edit: A couple warnings, if you decide to go with a MAC (and I think you should): (1) Use different keys for CBC and the MAC; (2) MAC the ciphertext, not the plaintext; (3) Concatenate the IV to the ciphertext before using the MAC.

share|improve this answer
    
Would you mind explaining how a MAC of the ciphertext could validate a correct passphrase (assuming independent keys)? I've noticed @CodesInChaos's comment above offering similar advice, but I don't see how a MAC of the ciphertext could be used to confirm that the ciphertext has been decrypted correctly. –  hunter Feb 20 '13 at 23:26
1  
The passphrase would be used to generate both the MAC key and the encryption key. So in that sense, they're not independent. But if you derive them from a pseudo-random function (PRF) using a master key (which is in turn derived from the passphrase), then the probability of an incorrect passphrase giving a correct MAC key but a incorrect encryption key is negligible. (If your PBKDF algorithm gives you enough bits for both an encryption key and a MAC key, then you can forgo the PRF). –  Seth Feb 21 '13 at 0:22
    
Ok, that all makes sense. For (1) above, is it a problem to 'split' hash output into two 16-byte sets? I'm currently using $sha512 \longrightarrow bcrypt \longrightarrow sha256$ for my passphrase. Should I simply make the final step $sha512$ and split the output: half to AES and half to the MAC? Also, on (3): I'm storing the IV in the unencrypted header of the file. Why should I tack it onto the end of the ciphertext? –  Naftuli Tzvi Kay Feb 21 '13 at 2:54
    
The only reason I didn't set out to use a MAC in the first place is because there doesn't seem to be native support in Python as a part of PyCrypto for doing it. I've heard that doing a MAC wrong also can really open up a security hole. –  Naftuli Tzvi Kay Feb 21 '13 at 2:56
2  
You might want to Google PBKDF2 for handling the passphrase. Once you have a random "master" key M, you can do things like set your encryption key to HMAC(M, "Encryption key") and your MAC key to HMAC(M, "MAC key") [truncate the outputs as needed]. Or set the encryption key to AES(M,0x00...0000)AES(M,0x0...0001) and the MAC key to AES(M,0x00...0002). It doesn't matter where you store the IV, but when you compute the MAC, the IV needs to be part of the input string. Otherwise an attacker can mess with the IV to tamper with the plaintext - a common security hole. Not using a MAC is another. :) –  Seth Feb 21 '13 at 3:39

If you use an authenticated encryption mode (which you should be doing anyway) like GCM or EAX, this is a built-in feature.

Otherwise, use an HMAC.

share|improve this answer
    
Wish I could; Python support for authenticated AES modes is terrible (read 'nonexistent'). –  Naftuli Tzvi Kay Feb 21 '13 at 0:07
1  
Python has bindings to OpenSSL, does it not? If you have access to OpenSSL >= 1.0.1, it supports AES in GCM mode. –  Stephen Touset Feb 21 '13 at 0:19
    
It does, but I can't seem to find it. Is it in the OpenSSL.crypto package? Can't seem to find it here. –  Naftuli Tzvi Kay Feb 21 '13 at 0:25
    
@TKKocheran pyopenssl.sourceforge.net –  mikeazo Feb 21 '13 at 18:20

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.