I just came across this question, but it does not really answer my main concern that I have regarding password tokens.
To authenticate a client who is not logged in; I generate two random tokens and then use one as the DB selector, the other one as the validator, to authenticate an unknown client for a given operation, like resetting a password, etc.
My question is not regarding the generation of the hashes, that's all done. The thing is that I've been told to attach the base64 representation of the hashes to the reset password or whatever URL. Because it uses less space / is more efficient than HEX. That of course is true, but isn't that more dangerous for brute-force attacks, if you use a base64 string, which is shorter?
I think I see the confusion. Making the string shorter isn't like having a shorter password.
Shortening a password does make a brute-force attack faster, because the number of possible passwords gets smaller, so you have to try fewer passwords to brute-force it.
But encoding a fixed-size hash value in a different base (16 or 64) does not change the number of possible combinations needed to brute force it, so does not make brute forcing easier or faster, assuming the attacker has seen at least one example of the hash, so can guess what base it's encoded in.
Base64 is 2/3 the length of base16 (it encodes 6 bits per character instead of 4).
So let's say you are trying to brute-force a variety of different hashes. Let's calculate how many possible combinations you'll need to try, at worst.
A single, 24-bit integer: (16777216 possible values) ^ (1 integer) = 16777216 attempts. Well, duh, obvs.
A 4-character, base-64 string: (64 possible values) ^ (4 characters) = 16777216 attempts.
A 6-character, base-16 string: (16 possible values) ^ (6 characters) = 16777216 attempts.
A 24-character, binary string: (2 possible values) ^ (24 characters) = 16777216 attempts.
Notice how those numbers are all exactly the same. We have to try exactly the same number of different possibilities to find the correct one in each case, because they are all 24-bit values, just encoded in different ways.
Local articles referenced by this article: