Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Rand(), is it possible to guess the next number in a sequence? And generating better numbers

Tags:

php

random

If I generate a number using: $num=rand(0, 1000);, is it possible to guess what the next number will be?

Would I need to record a certain number of previously generated numbers? And how would I go about working out the next number?

Additional Information:

From random.org -

PHP Rand() imagePHP Rand() image

True random imageTrue random image

Thanks to Derobert's answer:

I used the method posted in his answer to generate the following image

openssl image OpenSSL image

I used the following code to do this:

// Requires the GD Library
header("Content-type: image/png");
$im = imagecreatetruecolor(512, 512)
    or die("Cannot Initialize new GD image stream");
$white = imagecolorallocate($im, 255, 255, 255);
for ($y=0; $y<512; $y++) {
    for ($x=0; $x<512; $x++) {
        if (random() === 1) {
            imagesetpixel($im, $x, $y, $white);
        }
    }
}       
imagepng($im);
imagedestroy($im);

function random(){
    $num = unpack('L', openssl_random_pseudo_bytes(4, $is_strong));


    if (!$is_strong) {
        echo 'error';
    }
    else{
        $lastDigit=substr($num[1], strlen($num[1])-1, 1);
        if($lastDigit<=4) return 0;
        return 1;
    }
}

Credits to Bo

like image 217
Drahcir Avatar asked Feb 03 '26 08:02

Drahcir


1 Answers

Yes, it's possible, php's rand is apparently just using the underlying C library's rand, which is a pseudo-random number generator.

How much output you'd need to observe depends on the exact algorithm used by the C library, which varies from platform to platform (and sometimes even version to version). The number of outputs you need to observer is probably fewer than ten.

If your C library is particularly bad, you could try mt_rand which uses the Mersenne Twister algorithm. Note that this is still predictable.

If you need unpredictable random numbers, then use openssl_random_pseudo_bytes and make sure crypto_strong is true afterwards. Note that it returns a binary string; to get a number you'll have to use something like unpack:

$num = unpack('L', openssl_random_bytes(4, $is_strong));
if (!$is_strong) {
    ... // handle error
}

Also note that will return a number between 0 and 2³²=4294967296, not 0–1000, so you'll need to deal with that.

like image 151
derobert Avatar answered Feb 05 '26 21:02

derobert