Replace rand () with openssl_random_pseudo_bytes ()

I need a replacement for the PHP rand() function, which uses a cryptographically strong random number generator.

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

I believe the key is to get openssl_random_pseudo_bytes() output in an integer, then you can do any math you need. I can come up with several ways to iterate from a string of bytes to an integer, but I was hoping for something ... elegant.

+15
php random cryptography
Aug 21 '09 at 17:24
source share
7 answers

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; } 
+11
May 13 '14 at 7:19
source share

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

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

At this point, you can do any math you want to get in the range you need. Another option (fraudster) that you have is to run a system command to generate a random number - there are some good options for random number generators for various operating systems available on the Internet.

+8
Aug 21 '09 at 18:49
source share

Here is a version of the above solutions that does not use recursive function calls:

 function secure_rand($min,$max) { $range = $max - $min + 1; if ($range == 0) return $min; $length = (int) (log($range,2) / 8) + 1; $max = pow(2, 8 * $length); $num = $max + 1; // Hackish, I know.. while ($num > $max) { $num = hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s))); } return ($num % $range) + $min; } 
+2
May 13 '14 at 3:22
source share

Since PHP 7 is currently missing, the easiest way to solve this problem is to replace all instances of mt_rand with random_int .

(Suppose you updated, that is.)

+2
Dec 09 '15 at 7:38
source share

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

 print hexdec('45261b8f'); > 1160125327 
+1
Aug 21 '09 at 19:07
source share

The easiest way to do this (and the safest of all the options here) is to use CryptoLib, which has a randomInt function that provides a replacement for rand.

First download CryptoLib and paste it into your project: https://github.com/IcyApril/CryptoLib

Two, run this code. replace the path / with / with the cryptolib.php and min max directory with the minimum and maximum numbers:

 <?php require_once('path/to/cryptoLib.php'); $min = 1; $max = 5; $randomNum = CryptoLib::randomInt($min, $max); ?> 

Full CryptoLib documentation: https://cryptolib.ju.je/

0
Dec 29 '15 at 12:52
source share
 function ($min,$max){ $range = $max-$min+1; do{ $result = floor($range*(hexdec(bin2hex(openssl_random_pseudo_bytes(4)))/0xffffffff)); } while($result == $range); return $result + $min; } 
-one
Oct. 27 '14 at 2:02
source share



All Articles