PHP 7 standard library provides the random_bytes[$length]
function that generate cryptographically secure pseudo-random bytes.
Example:
$bytes = random_bytes[20];
var_dump[bin2hex[$bytes]];
The above example will output something similar to:
string[40] "5fe69c95ed70a9869d9f9af7d8400a6673bb9ce9"
More info: //php.net/manual/en/function.random-bytes.php
PHP 5 [outdated]
I was just looking into how to solve this same problem, but I also want my function to create a token that can be used for password retrieval as well. This means that I need to limit the ability of the token to be guessed. Because
uniqid
is based on the time, and according to php.net "the return value is little different from microtime[]", uniqid
does not meet the criteria. PHP recommends using openssl_random_pseudo_bytes[]
instead to generate cryptographically secure tokens.
A quick, short and to the point answer is:
bin2hex[openssl_random_pseudo_bytes[$bytes]]
which will generate a random string of alphanumeric characters of length = $bytes * 2. Unfortunately this only has an alphabet of
[a-f][0-9]
, but it works.
Below is the strongest function I could make that satisfies the criteria [This is an implemented version of Erik's answer].
function crypto_rand_secure[$min, $max]
{
$range = $max - $min;
if [$range < 1] return $min; // not so random...
$log = ceil[log[$range, 2]];
$bytes = [int] [$log / 8] + 1; // length in bytes
$bits = [int] $log + 1; // length in bits
$filter = [int] [1 $range];
return $min + $rnd;
}
function getToken[$length]
{
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "abcdefghijklmnopqrstuvwxyz";
$codeAlphabet.= "0123456789";
$max = strlen[$codeAlphabet]; // edited
for [$i=0; $i < $length; $i++] {
$token .= $codeAlphabet[crypto_rand_secure[0, $max-1]];
}
return $token;
}
crypto_rand_secure[$min, $max]
works as a drop in replacement for rand[]
or mt_rand
. It uses openssl_random_pseudo_bytes to help create a random number between $min and $max.
getToken[$length]
creates an alphabet to use within the token and then creates a string of length $length
.
Source: //us1.php.net/manual/en/function.openssl-random-pseudo-bytes.php#104322
gagarine
3,9632 gold badges29 silver badges39 bronze badges
answered Dec 5, 2012 at 22:25
ScottScott
11.7k4 gold badges26 silver badges48 bronze badges
30
Security Notice: This solution should not be used in situations where the quality of your randomness can affect the security of an application. In particular,
rand[]
anduniqid[]
are not cryptographically secure random number generators. See Scott's answer for a secure alternative.
If you do not need it to be absolutely unique over time:
md5[uniqid[rand[], true]]
Otherwise [given you have already determined a unique login for your user]:
md5[uniqid[$your_user_login, true]]
answered Dec 4, 2009 at 10:55
loletechloletech
3,6521 gold badge14 silver badges3 bronze badges
6
Object-oriented version of the most up-voted solution
I've created an object-oriented solution based on Scott's answer: