Good Solutions
This assumes a 256-bit nonce is required.
random_bytes(32)
(PHP 7.0.0+)
openssl_random_pseudo_bytes(32)
mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)
- Reading from
/dev/urandom
Code snippet for #4:
<?php
function getRandom($bytes)
{
// Read only, binary safe mode:
$fp = fopen('/dev/urandom', 'rb');
// If we cannot open a handle, we should abort the script
if ($fp === false) {
die("File descriptor exhaustion!");
}
// Do not buffer (and waste entropy)
stream_set_read_buffer($fp, 0);
$entropy = fread($fp, $bytes);
fclose($fp);
return $entropy;
}
Bad Solutions
mt_rand()
rand()
uniqid()
microtime(true)
lcg_Value()
What Makes a Solution Good?
A good solution should leverage a cryptographically secure pseudorandom number generator (CSPRNG). On Unix-based operating systems, this can be achieved by reading directly from /dev/urandom
.
But I don't understand how the token can be predictable.
This topic has been covered pretty in-depth before.
I have the following code:
<?php
srand(time());
$reset_password_token = rand(444444444444,999999999999);
?>
In theory, there would be only 555555555555 possible values for this. Unfortunately, the actual number is much lower.
rand()
uses an algorithm called a Linear Congruent Generator, which because of how it's implemented in PHP 5, only works with unsigned 32-bit integers. Both of the numbers you provided are larger than 2**32
. I'm not sure if it would overflow. The source code is not very enlightening in this case.
However, because you are seeding your random numbers with time()
, you are going to run into trouble. Quickly, run this code:
<?php
srand(1431223543);
echo rand()."\n";
You should see 1083759687
in your console. Generally, the time difference between computers on the internet is pretty small. You could probably account for only a possible jitter of up to 2 seconds in every timezone, and it would only take you 120 guesses (worst case) to begin predicting random number output. Forever.
Please, for anything at all related to the security of your application, use a CSPRNG.