views:

160

answers:

2

I need a replacement for PHP's rand() function that uses a cryptographically strong random number generator.

The openssl_random_pseudo_bytes() function gets you access to the strong random number generator, but it outputs its data as a byte string. Instead, I need an integer between 0 and X.

I imagine the key is to get the output of openssl_random_pseudo_bytes() into an integer, then you can do any math on it that you need to. I can think of a few "brute force" ways of converting from a byte string to an integer, but I was hoping for something ... elegant.


Edit

Using the suggestion from angrychimp, I've created a drop-in replacement for rand() using OpenSSL. I'll include it here for posterity:

function crypto_rand($min,$max) {
    $range = $max - $min;
    if ($range == 0) return $min; // not so random...
    $length = (int) (log($range,2) / 8) + 1;
    $num = hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s))) % $range;
    return $num + $min;
}
+2  A: 

The manual page for openssl_random_pseudo_bytes() has an example I think you want. You can just call bin2hex() on the output of openssl_random_pseudo_bytes() to convert to a hexadecimal number, then hexdec() on that value to convert to decimal.

$rand_num = hexdec(bin2hex(openssl_random_pseudo_bytes($length, $strong)));

At that point you can do whatever math you want to get a value in the range you need. The other (cheater) option you might have is to run a system command to generate a random number - there are a few good options for random number generators for various operating systems available online.

angrychimp
+1  A: 

well, just use hexdec on the result of openssl_random_pseudo_bytes and you will get your integer. It is as elegant as it gets :)

print hexdec('45261b8f');

>  1160125327
Anti Veeranna