11
$\begingroup$

I've been asked by a client to give some advice on hashing and as it isn't my area I'm looking for someone who knows what they are talking about.

The client is hashing 4-6 digit PINs (mostly 4 digit) with bcrypt, they have the work factor set as high as the business will allow them but they are worried that due to the small key space it will still be possible to reverse individual PINs. They are now thinking of encrypting the hashes before storing them to add an extra layer of protection. The encryption is fast enough to not affect login times so my suggestion of using the additional processing to increase the work factor instead was rejected.

What do people think? I can't see it hurting and adding the additional hurdle probably won't hurt but I've heard of odd interactions between different algorithms so don't want to say to do it without someone who knows their stuff looking at it.

$\endgroup$
  • 3
    $\begingroup$ I can absolutely assure you that 4 digit PINs will be in no way secure by "just" using standard password hashing algorithms. Want you need is to bring high entropy (ie encryption or HMAC'ing) into the mix or to outsource the verification to a rate-limiting secure processor. If an attacker can get hands on the hashed PIN, it will take him 10,000x to 1,000,000x the ressources you use for a single verification, so if you take 100ms for verification, an attacker will need 16 core-minutes to find the PIN and about a core-day at most when using similar cores to you.. $\endgroup$ – SEJPM Mar 8 '17 at 11:22
  • 1
    $\begingroup$ I see so mention of salting. You should consider adding that on top of everything so attackers can't pre-calculate all the hashes. $\endgroup$ – kichik Mar 8 '17 at 18:08
  • 3
    $\begingroup$ @kichik bcrypt is always salted $\endgroup$ – Stop Harming Monica Mar 8 '17 at 18:46
13
$\begingroup$

Your core problem is the fact that you only have about 20 bits of entropy at most (assuming users pick fully random 6-digit PINs which most probably won't). 20 bits of entropy also means that it takes an attacker at most 1,000,000 times the amount of work that you invest for verification to find the password, but the attacker can greatly parallelize the password search and he can use stronger, higher-clocked architectures than you are usingb potentially. So just relying on the password hash is really not an option here.

Right now, I see three solutions to your problem:

  • HMAC the password or the hash, this has the advantage of being very straightforward and being guaranteed to be non-invertible.
    Functionally equivalently one can also append a high-entropy secret to the PIN prior to bcrypt hashing (this is called "peppering" and has the drawback of blocking interoperability with the third approach).
  • Encrypt the password or the hash, this has the advantage that you could in theory with password hashes that allow it, upgrade the parameters without client-login, however if your encryption key gets leaked so gets the encrypted data
  • Outsource verification to a rate-limiting HSM, this has the advantage, that an attacker cannot possibly try passwords faster than the rate-limit

Your best option really would be to use a rate-limiting HSM which provides HMAC and then HMAC the bcrypt hashes or directly the passwords.


They are now thinking of encrypting the hashes before storing them to add an extra layer of protection.

Yes, this will bring security up from an attacker just having to exfiltrate and break the hash to an attacker having to exfiltrate and break the hash after he exfiltrated the encryption key (which you can prevent, right!?).

I can't see it hurting and adding the additional hurdle probably won't hurt but I've heard of odd interactions between different algorithms so don't want to say to do it without someone who knows their stuff looking at it.

While in theory there may be odd interaction, the probability of this happening in practice is negligible.

$\endgroup$
  • $\begingroup$ Why would it be an advantage that the HMAC is non-invertible? If the attacker learns the HMAC- or encryption key, the only difference is that the attacker needs to calculate the HMAC on each guess, instead of decrypting the hash once, to learn if the guess is correct. Since the attacker is brute-forcing a bcrypt hash, the overhead is negligible. When using encryption, if (big if) the key is leaked but the data isn't, you can actually change the key without invalidating all PINs. $\endgroup$ – knbk Mar 8 '17 at 12:23
  • 1
    $\begingroup$ @knbk assume the OP would ditch bcrypt because of the "minor" bonus it brings when it comes to security. Then with HMAC an attacker at least wouldn't learn cleartext PINs. $\endgroup$ – SEJPM Mar 8 '17 at 12:33
  • 7
    $\begingroup$ I guess you'd have to do rate limiting regardless of the method to protect the hash values themselves. It may also be an idea to feed the KBKDF (e.g. bcrypt in this example) a salt and a secret "pepper" instead of just a salt. That would be very similar to option 1. $\endgroup$ – Maarten - reinstate Monica Mar 8 '17 at 12:43
  • $\begingroup$ @MaartenBodewes Finally, someone mentioned the words "salt" and "pepper". I wonder why SEJPM didn't mention them in his answer somewhere while talking about the low entropy problem… $\endgroup$ – e-sushi Mar 8 '17 at 14:38
  • $\begingroup$ @e-sushi salt is by default unique per-hash for bcrypt and pepper isn't a default concept for bcrypt and the same effect can be achived by using HMAC (either on the password or the hash). $\endgroup$ – SEJPM Mar 8 '17 at 14:40

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.