Remix.run Logo
kbolino 9 days ago

Bcrypt alone is unfit for purpose. Argon2 does not need its input to be predigested.

It's easy for somebody who knows this to fix bcrypt, but silently truncating the input was an unforced error. The fact that it looks like and was often sold as the right tool for the job but isn't has led to real-world vulnerabilities.

It's a classic example of crypto people not anticipating how things actually get used.

(Otherwise, though, I agree)

daneel_w 9 days ago | parent [-]

Peppering is for protecting self-contained password hashes in case they leak. It's a secondary salt meant to be situated 1) external to the hash, and 2) external to the storage component the hashes reside in (i.e. not in the database you store accounts and hashes in). The method has nothing to do with trying to fix anything with bcrypt. You should be peppering your input even if you use Argon2.

kbolino 9 days ago | parent [-]

Right, but peppering was not part of my comment. You can't always pepper, and there are different ways to do it. It's (mostly) orthogonal to the matter.

You do not have to do any transformations on the input when using Argon2, while you must transform the input before using bcrypt. This was, again, an unnecessary and dangerous (careless) design choice.

daneel_w 9 days ago | parent [-]

I don't understand your responses here. Clearly you are not familiar with what problem peppering solves, or why it's a recommended practice, no matter what self-contained password hashing you use. bcrypt, scrypt, Argon2; they are all subject to the same recommendation because they all store their salt together with the digest. You can always use a pepper, you should always use a pepper, and there's only one appropriate way to do it.

kbolino 9 days ago | parent [-]

There are at least as many ways to pepper as there were to salt before salts became integral to the definition of a good KDF. To wit:

  KDF(password, salt XOR pepper, ...)
  KDF(password + pepper, salt, ...)
  KDF(password, AES128(salt, pepper), ...)
  KDF(HMAC-SHA256(password, pepper), salt, ...)
  ...
And no, you cannot always pepper. To use a pepper effectively, you have to have a secure out-of-band channel to share the pepper. For a lot of webapps, this is as simple as setting some configuration variable. However, for certain kinds of distributed systems, the pepper would have to be shared in either the same way as the salt, or completely publicly, defeating its purpose. Largely these are architectural/design issues too (and in many cases, bcrypt is also the wrong choice, because a KDF is the wrong choice). I already alluded to the Okta bcrypt exploit, though I admit I did not fully dig into the details.

The HMAC-SHA256 construction I showed above, and similar techniques, accomplishes both transforming the input and peppering the hash. However, the others don't transform the input at all or, in one case, transform it in a way even worse for bcrypt's use.