简体   繁体   中英

Big random number generation

I need a big (like, say, 128-bit big) random number generator in PHP. I was thinking in storing this number in a string as hexadecimal.

Note that this is meant for a login system that mentioned the need for a "random" number, so I'm guessing I really need it to be "random-enough" (because I know pseudo-random is never truly random).

The algorithm I was thinking was generating the number one hex digit at a time, then concatenating it all. Like this:

$random = '';
for ($i = 0; $i < 32; ++$i) {
   $digit = rand(0, 15);
   $random .= ($digit < 10 ? $digit : ($digit - 10 + 'a'));
}
return $random;

Can I trust this function to return good pseudo-random numbers or am I messing with something I really shouldn't?

Try:

for ($str = '', $i = 0; $i < $len; $i++) {
    $str .= dechex(mt_rand(0, 15));
}

I asked this question several years ago and, since then, my knowledge of this topic has improved.

First of all, I mentioned I wanted random numbers for a login system. Login systems are security mechanisms. This means that any random number generators that the login system relies on should be cryptographically secure .

PHP's rand and mt_rand are not cryptographically secure.

In these cases, it's best to be safe than sorry. There are random number generators designed specifically to be secure, notably openssl_random_pseudo_bytes (which is unfortunately not always available -- you must enable the OpenSSL extension for it to work). On *NIX systems (such as Linux), bytes read from /dev/urandom can be used as well.

Unfortunately (for the purposes of this question), both of these approaches return binary data instead of hexadecimal. Fortunately, PHP already has a function to fix this for us, bin2hex , which works for strings of any length.

So here's how the code would look like:

function generate_secure_random_hex_string($length) {
   // $length should be an even, non-negative number.

   // Because each byte is represented as two hex digits, we'll need the binary
   // string to be half as long as the hex string.
   $binary_length = $length / 2;

   // First, we'll generate the random binary string.
   $random_result = openssl_random_pseudo_bytes($binary_length, $cstrong);

   if (!$cstrong) {
      // The result is not cryptographically secure. Abort.
      // die() is just a placeholder.
      // There might be better ways to handle this error.
      die();
   }

   //Convert the result to hexadecimal
   return bin2hex($random_result);
}

// Example:
echo generate_secure_random_hex_string(32);

I've often seen this handled in login systems by just doing something like:

$salt  = "big string of random stuff"; // you can generate this once like above
$token = md5( $salt . time()); // this will be your "unique" number

MD5 hashes can have collisions, but this is pretty effective and very simple.

As of PHP 5.3:

function getRandomHex($num_bytes=4) {
  return bin2hex(openssl_random_pseudo_bytes($num_bytes));
}

For your example of 128 bits:

$rand128 = getRandomHex(16);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM