43

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?

behkod
  • 2,647
  • 2
  • 18
  • 33
  • 1
    http://php.net/manual/en/function.random-int.php *"Returns a cryptographically **secure** random integer in the range min to max, inclusive."* and http://php.net/manual/en/function.rand.php *"This function **does not generate cryptographically secure** values"* – Funk Forty Niner May 28 '17 at 15:08
  • *"Which one is faster?"* - Run a benchmark and find out. – Funk Forty Niner May 28 '17 at 15:08
  • @Fred-ii- thank you. But what does "cryptographically secure **pseudo-random**" mean? – behkod May 28 '17 at 15:10
  • 2
    https://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator --- https://stackoverflow.com/questions/2449594/how-does-a-cryptographically-secure-random-number-generator-work – Funk Forty Niner May 28 '17 at 15:11
  • 3
    use `rand()` unless you need a securely randomized integer, then use `random_int()`. If you don't know if you need the latter, you probably don't (it impacts "guessability", so imagine where that's useful). If you're trying to randomize a slideshow, for instance, `rand()` is just fine. – Jared Farrish May 28 '17 at 15:43
  • 1
    On the speed thing, again unless you know you need it, don't prematurely optimize based on that. Focus on the application of the function and later on adjusting for efficiency if necessary. – Jared Farrish May 28 '17 at 15:47
  • Thank you @JaredFarrish. – behkod May 28 '17 at 16:55
  • 1
    `mt_rand()` superseded `rand()` in PHP 7.1. Just wondering why that hasn't been mentioned? – Chuck Le Butt Nov 19 '17 at 23:15

6 Answers6

32

Revisiting the question and seeing there's been an answer given, I find it's only fair that I submit my comments to an answer, seeing they were submitted before.

The manual on PHP 7's random_int() function states:

"Returns a cryptographically secure random integer in the range min to max, inclusive."

and for rand()

*This function does not generate cryptographically secure values" *

OP's comment:

"@Fred-ii- thank you. But what does "cryptographically secure pseudo-random" mean? – NDFA"

That can be found in the following links as per my findings:

Which states:

A cryptographically secure pseudo-random number generator (CSPRNG) or cryptographic pseudo-random number generator (CPRNG)[1] is a pseudo-random number generator (PRNG) with properties that make it suitable for use in cryptography.


In regards to performance, you will need to run a benchmark yourself.

Funk Forty Niner
  • 74,450
  • 15
  • 68
  • 141
32

Starting with PHP 7.1, rand() is an alias for mt_rand(). The newer random_int() is the slowest, but only secure method of the three.

<?php

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += rand(0, 32767);
}
printf('[rand] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += mt_rand(0, 32767);
}
printf('[mt_rand] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

$start = microtime(true);
$sum = 0.0;
for ($i = 0; $i < 10000000; $i++) {
    $sum += random_int(0, 32767);
}
printf('[random_int] Time: %.3f s%s', microtime(true) - $start, PHP_EOL);

Results on PHP 7.4:

[rand] Time: 0.320 s      
[mt_rand] Time: 0.326 s   
[random_int] Time: 9.255 s
Matt Janssen
  • 1,505
  • 13
  • 14
7

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.

3

As most number generators, using rand() is not secure because it does not generate cryptographically secure values and the output of rand() is predictable.

PHP 7.0 introduces random_bytes and random_int as core functions which are free from the problems that most of random number generators have.

T. AKROUT
  • 1,719
  • 8
  • 18
  • 6
    That's just wrong. First, it's not a problem, it's by design, cryptographically unsafe functions like rand() are generally faster than crypto-safe functions, so if you're not using it for something related to security, it's better to use non-safe functions. You can't really compare crypto-safe and crypto-unsafe functions, their usage is just really different. – Rikudou_Sennin Sep 19 '18 at 21:23
2

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, which seems to have actually increased the speed of both cases.

Rafael Kuhn
  • 67
  • 1
  • 3
1

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.

ion
  • 540
  • 7
  • 20