As mentioned in this wonderful link, the way to get a PBKDF2 Hash of a user given password given

  1. a password (of course),
  2. a salt (generated Cryptographically Secure Random Number Generator.
  3. iteration count (chosen high enough to be secure while balancing your application's usability tolerance)
  4. Hash size (length of the hash to be computed)

/** * Computes the PBKDF2 hash of a password. * * @param password the password to hash. * @param salt the salt * @param iterations the iteration count (slowness factor) * @param bytes the length of the hash to compute in bytes * @return the PBDKF2 hash of the password */ private static byte[] pbkdf2(char[] password, byte[] salt, int iterations, int bytes) throws NoSuchAlgorithmException, InvalidKeySpecException { PBEKeySpec spec = new PBEKeySpec(password, salt, iterations, bytes * 8); SecretKeyFactory skf = SecretKeyFactory.getInstance(PBKDF2_ALGORITHM); return skf.generateSecret(spec).getEncoded(); } Now my question is :

How should the Keyed hashing for the password be implemented ?

Based on my reading, this is my line of thinking. Please validate.

  • Keep the salt argument to the method pbkdf2 (in the code snippet above) secret (obtain it from a highly secure HSM as opposed to storing it in the database alongside the password hash when needed).

  • Since the salt is meant to be random (to protect them from the rainbow tables / dictionary attacks), the salt provided to the pbkdf2 should be a concatenation of the key and a random bytes generated from a CSPRNG.

    [salt] = [secret key] + [random bytes from a CSPRNG]

Finally, I will dare to ask a silly question (will dare to ask since high iteration count is posing a serious usability issue since we need to authenticate for 90% of the use cases in our application)

Can we reduce the iteration count OR do without it since we have added an additional layer of security through the Keyed hashing ?

P.S: I am aware of the value that slow hashing algorithms add by reducing the possibility of passwords getting compromised through brute force attacks. Just want the experts to comment on the security value addition through Keyed Hashing VS having a Slow Hashing algorithm with non-secret salt.


1 Answer 1


One way to combine password hash with a secret key is to have a separate device (i.e. HSM) which encrypts password hashes sent from auth server using a key only known by the device itself.

At user login, your auth server calculates a slow hash (say, bcrypt) with proper cost setting (whatever is tolerable for the server/situation, 5ms, 20ms, 100ms?) and passes the resulting hash to the encryption device, which in turn returns the encrypted blob which you can verify on the auth server (auth server stores hash identifier, cost, salt, possible "encryption device key identifier material" and the encrypted blob).

The "encryption device" will not allow the auth server to decrypt hashes, only encrypt and return the encrypted blob to auth server.

The separate key adds another layer of security if it is not under the same thread model than the auth server/hash database.

Using a separate, narrow access device which holds a strong key defeats attacks that get hold of the leaked user database (and auth server files).

  • This is interesting. Is caching the hash for a given password and the response (encrypted blob) from the hsm for the password hash a good idea? I'm trying to optimize and improve the verification performance.
    – acthota
    Commented Nov 28, 2014 at 2:59
  • 1
    My concern is that in our application, high number of iterations and the slow password verification that entails (obviously for security) makes usability a HUGE issue.. Authentication is done on every request made to the server. "Security at the expense of usability comes at the expense of Security" is what I read in one of the answers on Stack Overflow... in our case it also comes at the expense of our product viability :)
    – acthota
    Commented Nov 28, 2014 at 5:51
  • Use a lower stretching cost on the auth server, but use at least some. For example, 1ms stretching time buys you alot compared to non-stretched hashes. These slides are also worth to check: openwall.com/presentations/YaC2012-Password-Hashing-At-Scale At the slides the example uses HMAC with secret key, but if you use (reversible) encryption, you get the benefit of having the possibility to update the "secret key" at anytime.
    – timoh
    Commented Nov 28, 2014 at 7:16
  • 1
    Had to break it into multiple comment due to the length limitation. Still I would like to know if going with a PBKDF2 hash with the salt being a combination of (Cryptographically generated random value - CGRV) AND (Secret / Pepper) is a good option. I specifically want to know if the secrecy of the PEPPER is in anyway affected in the case of a breach when attacker has the HASH and the (CGRV) part of the salt in his hands for offline analysis. To paraphrase, can they deduce the pepper by doing the analysis on the HASH and the CGRV across multiple rows in the breached database ?
    – acthota
    Commented Nov 28, 2014 at 14:19
  • 1
    Secrecy of the pepper shouldn't be affected (as far as I'm aware of) if you do PBKDF2 operation where the salt consist of a pepper and "regular salt" (and the adversary get hash and part of the salt but not the secret from the HSM). However, this is not how PBKDF2 was designed to work and is home made construction which naturally should be avoided. Also, the HSM is not being used optimally, since the pepper becomes now readabale by the auth server (it needs the secret "as is" to be able to calculate the PBKDF2 hash).
    – timoh
    Commented Nov 28, 2014 at 22:27

You must log in to answer this question.

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