3 ms·
Ask HN: Bad idea to use sha256 with bcrypt to bypass the 72 length truncation?
I'm wanting to hash access tokens for an app while retaining a way to perform
fast lookups on the token and the token's account, without requiring additional
headers for the account/token IDs.
I figured I could generate tokens in the form of
{account_uuid}.{token_uuid}.{random_token}
but since the app is using UUIDs (32 chars with dashes stripped), the padding
on the front of the tokens ends up being 66 chars in of itself (including the
2 dots), only leaving 6 chars for the random token (which is actually 64 bytes).
So I figured that hashing the token using sha256 would work out, since the
token would end up being 64 chars.
The hashing flow would look like,
1. Client requests a new token
2. Generate token using above form
3. Hash using sha256
4. Hash and store with bcrypt
5. Respond to client with raw token
In the end, the lookup and comparison flow would look like,
1. Extract UUIDs from token
2. Lookup account by UUID
3. Lookup token on account by UUID
4. Secure comparison of token
Is there a security concern here that I'm missing? I'd like to be educated.
(Disclaimer: this is being done solely for access tokens – not passwords.)
- viraptor 10y agoA few issues... and maybe things I don't understand from the description: - Why do you want to use bcrypt? You could even use enough rounds of only sha256 instead. - You don't even need a hashing scheme with salt, because your token contains salt by definition. - Your lookup sounds complicated. Getting rid of salt from the hashing algorithm allows you to do a single lookup - for the hash of the token. (and then optionally a check that account/token uuids match) - Plan for the future - prefix this hash with "1.", "v1." or something like that. You may want to update it one day. - If you do want to follow with the current plan, you can ignore the first two uuids when hashing. You can easily hash only the random token part with bcrypt for storing in the database. (bcrypt adds its own salt by default) - You didn't mention expiration check. Maybe you planned it, but if not - think about it. Finally - is that a security concern? Depends on what you're concerned about. Using sha256 and bcrypt effectively limits your key space to (at most) the smaller output. bcrypt gives you 184 bits, sha256 gives you 256 bits. So by doing sha256 you shouldn't lower the security of the scheme.
- ezekg 10y agoAppreciate the response. I'm using bcrypt simply because it's what I was using before we moved to UUIDs and this truncation issue was introduced; it's not a requirement. I did think about simply ignoring the UUIDs when hashing, and append it before sending it back to the client. I may revisit that. The reason I'm not doing a lookup for the token itself (skipping the account) is because we're using postgres schemas, so I need to switch to the correct account before querying for the token. Good points about tokens already containing salt, as well as prefixing the tokens with a version. I'll keep that in mind. And yes, the token expiry's are handled on the token model itself.