Using the provided suggestions, I created a replacement for rand () using OpenSSL. I will include it here for posterity.
The $ pedantic parameter provides results without bias, starting from the moment when the results are not evenly distributed within the possible range.
function crypto_rand($min,$max,$pedantic=True) { $diff = $max - $min; if ($diff <= 0) return $min; // not so random... $range = $diff + 1; // because $max is inclusive $bits = ceil(log(($range),2)); $bytes = ceil($bits/8.0); $bits_max = 1 << $bits; // eg if $range = 3000 (bin: 101110111000) // +--------+--------+ // |....1011|10111000| // +--------+--------+ // bits=12, bytes=2, bits_max=2^12=4096 $num = 0; do { $num = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes))) % $bits_max; if ($num >= $range) { if ($pedantic) continue; // start over instead of accepting bias // else $num = $num % $range; // to hell with security } break; } while (True); // because goto attracts velociraptors return $num + $min; }
tylerl May 13 '14 at 7:19 2014-05-13 07:19
source share