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?

John
  • 2,242
  • 2
  • 28
  • 45

2 Answers2

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.

Thomas Pornin
  • 320,799
  • 57
  • 780
  • 949
  • 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](http://security.stackexchange.com/a/2206/971). – D.W. Sep 03 '12 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 Sep 04 '12 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 Apr 11 '13 at 11:43
  • From the description of the problem, it appears that the configuration file is only ever encrypted once. – Stephen Touset Apr 11 '13 at 17:06
  • @boo9: it's my fault, I had left a bit implicit. Now fixed: the PBKDF2 salt must be file-specific (i.e. a new salt for each encryption, the salt is encoded in the file header). – Thomas Pornin Apr 11 '13 at 17:12
  • 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? – Dheeraj Vepakomma Jun 06 '14 at 06:41
  • @ThomasPornin: Maarten Bodewes states in this answer https://stackoverflow.com/a/12462088/774398 that you should not reuse the IV if you reuse the key; your example uses a passphrase, so key and IV are always the same - do you see an issue with that? My question is basically regarding deriving IV vs. generating random IV every encryption – Patrick Oct 29 '18 at 11:26
  • 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. – Thomas Pornin Oct 29 '18 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!

Polynomial
  • 132,208
  • 43
  • 298
  • 379
  • "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 Sep 04 '12 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 Sep 04 '12 at 13:54