2

The first time a user logs in to our app, we derive an AES key from their password using PBKDF2. The AES key is kept in RAM only and used to encrypt and wrap other keys and data during the session.

When the current session ends, we throw away the key but keep the encrypted data and the derivation settings (salt/iteration count/etc.) for next time.

On subsequent logins, we re-derive the key based on the password and settings, but want to check the key (password) is valid (to some reasonable level of confidence) before attempting to use it.

We don't want to also compute a hash over the password because the key derivation is already (deliberately) long-running and we don't want to make that process longer with another long-running hash algorithm.

I've seen a few solutions to this but I'm wondering if there is any standard that should be followed. What I've seen so far:

  • In Cryptography Engineering, Schneier et al suggest taking hash data from the n-1th iteration of your derivation function and hashing that with the salt, password, etc. to form a verification code. You can store this, and compute the same code for the candidate while you derive the key. If they don't match, you reject. Downside: If using third-party crypto libraries, it probably won't be possible to get access to the internal state of PBKDF2 to do this.
  • Compute something like SHA256(key+salt+password) and store that. Compute for the candidate and reject if they don't match.
  • Use the key to encrypt something with a known pattern or suffix, and store that. e.g.

    E(key, <32 bytes random data> + <32 bytes of 0>`.
    

    Store this, decrypt using the candidate key and check if the suffix matches. The number of 0s you choose determines the chance of a false positive.

The latter seems simple and effective, but I'm looking for clear advice from an expert/authority on the matter.

1

Normally, when you encrypt with a symmetric key, you also want to include some integrity check (a MAC) to detect alterations. There are very few attack models where attackers who can observe data cannot also modify data, so some sort of integrity check is normally needed.

The integrity check can be a stand-alone MAC algorithm, typically HMAC; or it can be integrated into the encryption mode (as in GCM). The latter is highly recommended because assembling an encryption system and a MAC securely is a lot more tricky than usually assumed (e.g. see this).

Assuming that your encryption system includes an integrity check, then the natural and safe method for verifying the correction of the password, in your situation, is to keep an encrypted small file with conventional contents -- decrypting the file entails verifying the MAC, hence the password (indirectly).

  • So in the case of validating the key outside any standard decryption operation, could a MAC be computed over some fixed string and stored? If the candidate key we have derived generates the same MAC on that string we know we have the right key? – Mike Weller Sep 3 '15 at 18:20
  • Or I guess use GCM mode to encrypt some small bit of random data. If we are able to decrypt with the candidate key, we're all good, don't even need to look at the decrypted data. That's probably a bit more straight forward. – Mike Weller Sep 3 '15 at 18:32
  • In practice, if K is the key derived from the password, then simply storing h(K) (for some hash function h) would be sufficient for verifying the password, but this is safe only as long as h(K) is "different" from what you use within the encryption system -- that is, if the encryption system really is "we hash K and use the result as key for AES" then showing h(K) is a deadly mistake ! I therefore suggest using the same encryption method for the password verification system, because, by definition, it won't suffer from such an inadvertent interaction. – Tom Leek Sep 3 '15 at 19:26
  • In other words, there is a common rule that says "a single purpose for each key" so if the key is to be used for encryption+MAC, then use it only for encryption+MAC. – Tom Leek Sep 3 '15 at 19:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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