I want to store a hash for authenticating a password. I also want to use the same password for decryption. Can I use PBKDF2 for both? (I plan to use different salts for the authentication and the decryption, of course, because otherwise the authentication result would be the decryption key!)

3 Answers
3

However, by invoking PBKDF2 twice (first to check the password, then to derive the actual key), you're essentially doubling a legitimate user's workload, whereas an attacker still only needs to run it once for each guessed password. Thus, you're cutting the legitimate user's advantage in half, or, equivalently, wasting one bit of password entropy.

(Also, the way PBKDF2 is defined, deriving more than one hash output length of key material is basically equivalent to invoking the whole PBKDF2 function two or more times, so you won't gain much that way. Other KDFs like scrypt may behave differently in this respect.)

Instead, I would recommend deriving a single "intermediate key" $K_I$ from the password $P$, using PBKDF2 with a suitably high iteration count, and then deriving both the password verification value $V$ and the actual encryption key $K_E$ from the intermediate key using a fast KDF (e.g. PBKDF2 with an iteration count of 1), like this:

where $S$ is the salt, $c$ is the iteration count, $\ell_P$ is the output length (in bytes) of the PRF used to instantiate PBKDF2, and $\ell_V$ and $\ell_{K_E}$ are the desired byte lengths of the verification token $V$ and the encryption key $K_E$ respectively, and $\|$ denotes their concatenation.

(The reason for choosing the intermediate key length as $\max(\ell_P,\ell_V,\ell_{K_E})$ is that we want the intermediate key to be at least as long as each of the final outputs $V$ and $K_E$, and there's no point in asking for output shorter than what the PRF naturally gives us; in fact, an even better choice could be $\max(\ell_V,\ell_{K_E})$ rounded up to the next multiple of $\ell_P$.)

The point about halving the attacker's workload is convincing!
–
EyalAug 17 '12 at 1:02

2

As pointed in this other answer, the simplest way to solve the halved workload issue is to generate a wide output with one invocation of the KDF, and split that in two parts. On a different issue: when we care for the cost of attack, Scrypt is significantly better than PBKDF2, because it forces the adversary to mobilize RAM during attacks.
–
fgrieuAug 17 '12 at 7:28

@fgrieu: That works, but is needlessly slow if the total amount of key material to be generated is more than the output length of the KDF used to instantiate PBKDF2. (Of course, if an attacker also needs to generate the same amount of key material to test each password guess, then the slowdown applies to them too, but that's not the case in the OP's scenario.)
–
Ilmari KaronenAug 17 '12 at 21:04

Another application is password checking, where the output of the key
derivation function is stored (along with the salt and iteration
count) for the purposes of subsequent verification of a password.

Also (as mentioned in the comments of this post), the memo also says (emphasis mine):

It is expected that the password-based key derivation functions may
find other applications than just the encryption and message
authentication schemes defined here. For instance, one might derive a
set of keys with a single application of a key derivation function,
rather than derive each key with a separate application of the
function. The keys in the set would be obtained as substrings of the
output of the key derivation function...

So you could use just one application of PBKDF2 to produce both the key, and the stored hash.

If you look at the algorithm, it would (depending on the underlying hash function and required key lengths), essentially be applying PBKDF2 twice - but with slightly different salts.

That should OK. PBKDF2 has sufficient collision resistance and pre-image resistance for password authentication, and the fact that the passwords to both are the same shouldn't cause any problems if the salts are different.