
Ask HN: Bad idea to use sha256 with bcrypt to bypass the 72 length truncation? - ezekg
I&#x27;m wanting to hash access tokens for an app while retaining a way to perform
fast lookups on the token and the token&#x27;s account, without requiring additional
headers for the account&#x2F;token IDs.<p>I figured I could generate tokens in the form of<p><pre><code>    {account_uuid}.{token_uuid}.{random_token}
    </code></pre>
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.<p>The hashing flow would look like,<p><pre><code>    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
</code></pre>
In the end, the lookup and comparison flow would look like,<p><pre><code>    1. Extract UUIDs from token
    2. Lookup account by UUID
    3. Lookup token on account by UUID
    4. Secure comparison of token
</code></pre>
Is there a security concern here that I&#x27;m missing? I&#x27;d like to be educated.<p>(Disclaimer: this is being done solely for access tokens – not passwords.)
======
viraptor
A 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
Appreciate 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.

