To generate a secure URL-safe hash for password reset or email activation, which one of these functions would be more secure, bin2hex or base64_encode in the following application?
1. Generate token (using one of these):
$token = bin2hex(openssl_random_pseudo_bytes(32));
$token = strtr(base64_encode(openssl_random_pseudo_bytes(64)), "+/=", "XXX");
2. Store in database:
$token_hash = password_hash($token, PASSWORD_BCRYPT);
INSERT INTO hash_table SET token_hash='$token_hash', series='X'
3. Validate token:
SELECT token_hash FROM hash_table WHERE series='X'
if (password_verify($hash_from_url,$token_hash)) {
// Success
}
I noticed that when $hash_from_url is more than 72 characters, it doesn't make a difference anymore.
But wouldn't it be better to use base64, to get 61 different characters rather than bin2hex that uses only 16, assuming I use a larger number of random bytes, for an equally long string, that is 72 characters of length?
The encoding itself doesn't actually change anything in regard of security.
As you already pointed out, bin2hex() will return longer strings as base64_encode() for the same number of bytes, because of the smaller base of possible characters. That means, if the length of the token is given, base64 encoding produces tokens with more entropy and is therefore better suited.
If your tokens are strong enough (min 20 characters a..z, A..Z, 0..9), you can use a simple hash function (e.g. SHA-256) without salting and keystretching instead of password_hash. This way you can create searchable hashes in the database.
Some time ago, I wrote a small class to generate base62 tokens of a certain length for password resets, maybe you want to have a look at the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With