PHP rand() vs. random_int()

Viewed 27794

As php.net indicates: random_int() function Generates cryptographically secure pseudo-random integers.

But, Can someone explain whats the difference between rand() & random_int()? Can I use random_int() instead of rand() when only requiring a random integer? Which one is faster?

6 Answers

rand()

rand() is now an alias for mt_rand(). Looking at the source code of mt_rand(), it can be seen the random number is not random at all. It's a simple mathematical computation not much more complex than

return $min + suffle_bits($internal_counter++) % ($max - $min);

where suffle_bits() is some predictable binary arithmetic to make it looks like $internal_counter is not just incrementing itself.

That's why rand() is said to returns pseudo-random numbers. The returned numbers seem to be drawn at random but knowing the value of the $internal_counter lets you predict what will follow.

random_int()

random_int() doesn't suffer from this predictability issue provided the computer's entropy generator is properly primed.

Guessing the next value is not possible even if an attacker collects a huge number of values.

Which one is best

If an attacker can guess the value of the $internal_counter from the output of your code and use that knowledge to interfere with the intended purpose of your code, then use random_int().

If the random number is used to display, let's say, a random greeting, then rand() is perfectly safe.

Now, if a long list of GUID or barcodes must be generated and the end user must not be able to guess another valid value from a subset, then random_int() is better not only for security but also because it doesn't repeat itself. rand() may repeat itself as quickly as 32768 output depending on the platform.

Which one is faster

Without any doubt, rand() is simpler and, therefore, faster.

Here is a crude one-line easy to copy/paste command to count how many numbers can be drawn from rand() in 10 seconds:

php -r '$s=microtime(true);$c=0;while(microtime(true)-$s<10){rand(0,9);$c++;};echo "$c\n";'

And the same for random_int():

php -r '$s=microtime(true);$c=0;while(microtime(true)-$s<10){random_int(0,9);$c++;};echo "$c\n";'

The counters for php 7.3 are:

rand():       36665142
random_int(): 10511327

rand() is less than 4 times faster. Unless speed is an issue, random_int() is the way to go but for the most basic non critical missions.

Complementing Frédéric response, in PHP 8.0.3, random_int() seems to be a lot faster than before, using his own code example.

with:

<?php
    echo "this will take 20 seconds\n\n";
    
    echo "generating random with 'rand' method\n";
    $s1=microtime(true);$c1=0;while(microtime(true)-$s1<10){rand(0,65535);$c1++;};
    $fc1 = number_format($c1 , 0, ',', '.');
    echo "generated: $fc1\n\n";
    
    echo "generating random with 'random_int' method\n";
    $s2=microtime(true);$c2=0;while(microtime(true)-$s2<10 {random_int(0,65535);$c2++;};
    $fc2 = number_format($c2 , 0, ',', '.');
    echo "generated: $fc2\n\n"; 
?>

I got the output:

this will take 20 seconds

generating random with 'rand' method
generated: 48.423.988

generating random with 'random_int' method
generated: 30.843.067

in his tests, random_int() was more than three times slower than rand().

in these, random_int() is just about 40% slower than rand().

PS: I've incremented the maximum random value from 9 to 65535 for personal uses, seems to have actually increased the speed of both cases.

I have not personally encountered any problems using random_int but it should be used with try/catch as it throws an exception if it was not possible to gather sufficient entropy.

Related