Encrypting bcrypt hashes 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.
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.