10

I'm writing a desktop application where I'm using PBKDF2 to generate an encryption key to AES-128 encrypt the config file. The config file contains a crypo-random key that's been used to encrypt the data for the program. The user already entered that key as provided from us on installation. The idea is they enter the crypto random key once and then they can use an easier to remember password. So far so good.

So, when the user loads the program, they enter the password. We used the password to regenerate the PBKDF2 key and decrypt the config file.

Now, how do I easily verify that the user entered the correct password? Of course, if they entered an incorrect password, decryption of the data won't work. But I'd like to reject the password immediately rather than letting the program load and then the user gets a decryption error message box.

I've read that TrueCrypt encrypts a known constant, the string "TRUE" and then verifies that the password-based key will encrypt "TRUE" to the same ciphertext. I've also read about generating an HMAC-SHA hash to verify the encrypted data. But that you don't want to use the same key for the MAC and to encrypt the data. For this reason, I like TrueCrypt's method (I don't have to track two sets of salts and IVs). I don't really care if an attacker can load the program. They won't be able to read any data. I just don't want the user to get in with the wrong password and think the program is insecure.

What's the right way to do this?

2 Answers 2

11

It depends whether you want to defend against typing mistakes, or attacks.

If you just want to defend against typing mistakes, just include some structure in your configuration file. E.g., define that your configuration file MUST begin, when decrypted, with the string "This is configuration file for application FooBar". If you do not find that string upon decryption, then the key is wrong.

If you want to defend against attacks (a bad guy voluntarily alters parts of the encrypted configuration file to make you load an incorrect key), then you need something stronger. The "right" solution is to use an authenticated encryption mode (my favourite is EAX). If your programming framework does not include an implementation of EAX mode, you can do something like this:

  • From the user's passphrase, generate 384 bits of key (PBKDF2 is a "key derivation function", it can be used to produce keys of arbitrary length). Split these into three 128-bit keys K1, K2 and K3.
  • Encrypt the configuration file with AES-128-CBC, using K1 as key and K2 as IV. Call the result C (the encrypted file).
  • Compute a MAC value over C, using key K3. For the MAC function, use HMAC with SHA-256 (or SHA-1, but SHA-256 is preferred on a general basis). The MAC is stored along C (appended, as header, as a separate file... that's your choice).
  • When decrypted, to the reverse: obtain the three keys from PBKDF2, verify the MAC, and (only if the MAC was correct) decrypt the file.

This scheme would resist both attacks and typing mistakes (however, it does not distinguish between a wrong passphrase and a genuine attack).

Edit: I had left it implicit, but it would be better to state it plainly: since we are using PBKDF2, there is a salt which is used to turn the password into the PBKDF2 output. Each encrypted file SHALL have its own salt. The salt SHALL be encoded in the file header. If a file is "re-encrypted", a new random salt SHALL be generated.

8
  • A good answer. I recommend using authenticated encryption in any case (i.e., either EAX or Thomas's alternative suggestion). One of the most common mistakes is to use encryption without message authentication; that often leads to security vulnerabilities, so you should always use some form of authenticated encryption, any time you are encrypting.
    – D.W.
    Commented Sep 3, 2012 at 20:10
  • I'm not sure I agree with your authentication scheme for the encrypted method, but for now the first option suffices. Thanks!
    – John
    Commented Sep 4, 2012 at 13:27
  • "Encrypt the configuration file with AES-128-CBC, using K1 as key and K2 as IV. Call the result C (the encrypted file)." In this scheme this fixates IV, next encryption with same password yields same IV. Should we rather have random IV every time ?
    – boo9
    Commented Apr 11, 2013 at 11:43
  • 1
    @ThomasPornin N00b question: If the salt is encoded in the file, will it not compromise security? In my case I wish to use PBKDF2 on a 4-digit passcode. If the attacker knows the salt and the number of iterations (by decompiling the source), is it not trivial to brute-force? Commented Jun 6, 2014 at 6:41
  • 1
    @patrickf I was indeed unclear, but that's the point of my "edit" section (added back in 2013): since keys are obtained from PBKDF2, and PBKDF2 has a "salt" parameter (which is basically the same as "nonce"), the resulting keys (encryption key, encryption IV, MAC key) will be different for each file. Commented Oct 29, 2018 at 14:04
1

TrueCrypt's mechanism is probably the best option here. You can verify whether the password was correct after decrypting only a single block, and it requires no extra security considerations.

Introducing extra hashing and verification leaves you vulnerable to any weaknesses in those algorithms. In this case, you're relying solely on the security of your cipher, which you're also relying on to secure your data. If AES-128 is broken, having "TEST" incorrectly identified as valid is the least of your worries!

2
  • "If AES-128 is broken" - you mean if someone finds a vulnerability in the AES cipher that can be exploited to break encryption? If that ever happened it would destroy computer security... The "extra hashing" would by cryptographically secure according to accepted standards
    – John
    Commented Sep 4, 2012 at 13:29
  • @John My point is that if AES-128 is found to be broken in future, the fact that you're incorrectly validating the "TEST" string as correct would be the least of your worries, since your entire data is compromised.
    – Polynomial
    Commented Sep 4, 2012 at 13:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .