What's the reason behind bcrypt(userId + username + password) rather than just bcrypt(password) ?
Okta Bcrypt incident lessons for designing better APIs
111–120 of 169 posts
Re: Okta Bcrypt incident lessons for designing better APIs
#112Earlier quoted context omitted.
hmac-bcrypt solves that problem very well, and should replace plain bcrypt: https://github.com/epixoip/hmac-bcrypt
I don't think it's a good idea for people to adopt new bcrypt constructions so that they can use it to generate cache keys (or, worse, other keys). (I need that "man standing up in the town hall meeting" meme for this.) Just use a real KDF, if that's really what you want. I'm still confused what password-derived material is doing in a Redis key.
Re: Okta Bcrypt incident lessons for designing better APIs
#113What's the reason behind bcrypt(userId + username + password) rather than just bcrypt(password) ?
What if two different users have the same password?
Re: Okta Bcrypt incident lessons for designing better APIs
#114Earlier quoted context omitted.
What if two different users have the same password?
Bcrypt is salted[1], so that shouldn't matter? [1]: https://en.wikipedia.org/wiki/Bcrypt#Description
bcrypt stores the salt and retrieves it for comparison - otherwise you wouldn't be able to generate a matching hash.
Consider the case where a user has a very long username and sets their password to their userId + username + password thus recreating the scenario which lead to the incident.
Re: Okta Bcrypt incident lessons for designing better APIs
#115Earlier quoted context omitted.
Or just a hash of the bcrypt hash, for the password! I don't like using thought-stopping cliches any more than anybody else does, but this design feels a little cargo-culted. All this stuff follows the more fundamental question of "why is the password mixed into a cache key"?
Yeah, I think both of the following would have worked if they wanted the password involved in a cache key and they wanted bcrypt to be used: * bcrypt(SHA-512(PW || stuff)) * SHA(stuff || bcrypt(PW)) Disclaimer: Not cryptography advice. It's still unclear to me why the password is in there.
Perhaps they did not want to apply cache invalidation purely by the passage of time, or want that passage of time to be long, but wanted to treat a credentials update as a cache invalidating event. A safer way to implement that would perhaps be to have a concept of a version of an account, incremented when authentication options or other significant properties change, and including that in the cache key.
I'm not sure why it would matter though: even if a credentials change does invalidate the cache from the PoV of the user looking up information, the information is potentially still in the cache so could still be referred to by someone else who has gained knowledge of the old credentials.
Re: Okta Bcrypt incident lessons for designing better APIs
#116Re: Okta Bcrypt incident lessons for designing better APIs
#117Can someone explain, in clear layman terms, what the difference is between a password hash and a KDF? I have went through this whole thread and tried to look around online but I still don't understand.
- MUST be non-reversible, including against tricks like "rainbow tables"
- should be somewhat expensive to discourage just trying all possible passwords against a (leaked) hash
KDF is a key derivation function. The value will be used as a key in, say, AES. The important properties are:
- should distribute entropy as well as possible, across the required width of output bits
- reversibility less important as the derived key shouldn't be stored anywhere
- may or may not want artificially inflated cost to discourage cracking
Re: Okta Bcrypt incident lessons for designing better APIs
#118Can someone explain, in clear layman terms, what the difference is between a password hash and a KDF? I have went through this whole thread and tried to look around online but I still don't understand.
Re: Okta Bcrypt incident lessons for designing better APIs
#119Can someone explain, in clear layman terms, what the difference is between a password hash and a KDF? I have went through this whole thread and tried to look around online but I still don't understand.
A password hash is a simple hash of a password. Hash algorithms are made to be fast. KDF - key deriving functions - are slow by design and are made to derive a key from a given string. They are designed to be slow to make password searching slower. This is a 2c tour of the topic.