New on LowEndTalk? Please Register and read our Community Rules.
All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.
All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.
Generating random integers with PHP
Microlinux
Member
in Help
Not being any sort of crypto or math expert, I adapted this code from some code I found.
Is anyone here able to verify if this is a valid way to generate cryptographically sound random integers in PHP?
Crypt::create_iv() uses openssl_random_pseudo_bytes() with an affirmative $crypt_strong flag.
public static function integer($max = PHP_INT_MAX, $min = 0)
{
$min = (int) $min;
$max = (int) $max;
$bits = 1;
if ($max < $min):
throw new RandomException('min is greater than max');
elseif ($min === $max):
throw new RandomException('min is equal to max');
endif;
$range = $max - $min + 1;
while ((1 << $bits) <= $range) {
$bits++;
}
$num_bytes = (int) (($bits + 7) / 8);
$mask = (1 << $bits) - 1;
do {
$data = Crypt::create_iv($num_bytes);
$result = 0;
for ($i = 0; $i < $num_bytes; $i++):
$result = ($result * 256) + ord($data{$i});
endfor;
$result = $result & $mask;
} while ($result >= $range);
return $result + $min;
}
Comments
What's wrong with rand(),
NVM on that.... but this seems weird to me...
Erm, rand() won't generate you cryptographically secure random numbers. Also, that's a method in a class, so error handling is being done by throwing exception, which is the correct way.
It's not in any way, shape or form, cryptographically strong.
I prefer handling errors with exceptions. You're going to be really horrified when I finish.
I don't know very much about the theory but to me, depending on random.org has been a better idea.
It's for a session class (other things eventually), so I'm not sure they'd appreciate the volume or if the latency would be acceptable.
Microlinux asks a very good question. I will let others respond regarding his PHP code.
An equally valid question is: How secure is the openssl random number generator that his code depends on? If it is running on a virtual machine (VPS), then it may not be starting with a good seed, nor is it gathering much entropy (randomness).
I'm not convinced that your approach uniformly distributed entropy from openssl_random_pseudo_bytes over the range. If 2^$bits is 1.2 times of the desired range, then doesn't that favor the beginning 20% of the range?
Also, use a library: https://github.com/ircmaxell/random_compat
Edit2: also this one, no idea what the difference is but..: https://github.com/ircmaxell/RandomLib
I feel like the virtualization would just introduce additional entropy. Anyway doubt you can get anything better than OpenSSL.
I guess what I'm confused about is how is max going to be less than min and why do you even need to pass in anything, why not always use the constant?
The function caller may wish to generate numbers between an arbitrary minimum and maximum; you could write a function that doesn't accept any inputs and just generates random 32-bit unsigned integer, but then this would be less useful to the caller. As the writer of a PHP function, you have no control over the specific integers that the caller will pass, except by throwing exceptions upon receiving bad inputs. In general it's preferable to build underlying functions to fail so that errors resulting from bad inputs don't propogate and make debugging complicated.
Not being an expert, that sounds like something valid to research.
I just need the bare minimum, but those examples give me something to evaluate against, thanks.
openssl_random_pseudo_bytes(32, $cstrong)
with some extra hashing maybeOn second thought, it looks fine, since you're actually looping until you get something within range; didn't realize that the first time.
Ok, thanks for the feedback!