openssl_random_pseudo_bytes

(PHP 5 >= 5.3.0, PHP 7)

openssl_random_pseudo_bytesYarı-rasgele dizge üretir

Açıklama

bool openssl_random_pseudo_bytes ( string $uzunluk , string $güçlü )

uzunluk karakterlik bir dizge döndürür. Ayrıca, ikinci değiştirgede bu yarı rasgele baytları üretmek için güçlü bir algoritma kullanılıp kullanılmadığı da belirtilecektir.

Değiştirgeler

uzunluk

İstenen dizgenin uzunluğu. Pozitif bir tamsayı olmalıdır. PHP, bu değiştirgeden bir pozitif tamsayı elde etmek için gerekli tür dönüşümünü yapacaktır.

güçlü

Güçlü bir algoritma kullanılmışsa bu değiştirgede TRUE döner. Bir hata oluşursa bu değer NULL olacaktır.

Dönen Değerler

İşlem başarılı olursa üretilen dizge, yoksa FALSE döner.

Örnekler

Örnek 1 - openssl_random_pseudo_bytes() örneği

<?php
for ($i = -1$i 5$i++) {
    
var_dump(bin2hex(openssl_random_pseudo_bytes($i$guclu)));
    
var_dump($guclu);
}

?>

Yukarıdaki örnek şuna benzer bir çıktı üretir:

string(0) ""
NULL
string(0) ""
NULL
string(2) "f6"
bool(true)
string(4) "8999"
bool(true)
string(6) "c202c9"
bool(true)
string(8) "45261b8f"
bool(true)

add a note add a note

User Contributed Notes 9 notes

up
32
nahun@telemako
4 years ago
Here's an example to show the distribution of random numbers as an image. Credit to Hayley Watson at the mt_rand page for the original comparison between rand and mt_rand.

rand is red, mt_rand is green and openssl_random_pseudo_bytes is blue.

NOTE: This is only a basic representation of the distribution of the data. Has nothing to do with the strength of the algorithms or their reliability.

<?php
header
("Content-type: image/png");
$sizex=800;
$sizey=800;

$img = imagecreatetruecolor(3 * $sizex,$sizey);
$r = imagecolorallocate($img,255, 0, 0);
$g = imagecolorallocate($img,0, 255, 0);
$b = imagecolorallocate($img,0, 0, 255);
imagefilledrectangle($img, 0, 0, 3 * $sizex, $sizey, imagecolorallocate($img, 255, 255, 255));

$p = 0;
for(
$i=0; $i < 100000; $i++) {
   
$np = rand(0,$sizex);
   
imagesetpixel($img, $p, $np, $r);
   
$p = $np;
}

$p = 0;
for(
$i=0; $i < 100000; $i++) {
   
$np = mt_rand(0,$sizex);
   
imagesetpixel($img, $p + $sizex, $np, $g);
   
$p = $np;
}

$p = 0;
for(
$i=0; $i < 100000; $i++) {
   
$np = floor($sizex*(hexdec(bin2hex(openssl_random_pseudo_bytes(4)))/0xffffffff));
   
imagesetpixel($img, $p + (2*$sizex), $np, $b);
   
$p = $np;
}

imagepng($img);
imagedestroy($img);
?>
up
7
powtac at gmx dot de
1 year ago
[Editor's note: the bug has been fixed as of PHP 5.4.44, 5.5.28 and PHP 5.6.12]

Until PHP 5.6 openssl_random_pseudo_bytes() did NOT use a "cryptographically strong algorithm"!
See bug report https://bugs.php.net/bug.php?id=70014 and the corresponding source code at https://github.com/php/php-src/blob/php-5.6.10/ext/openssl/openssl.c#L5408
up
5
acatalept at gmail
6 years ago
FYI, openssl_random_pseudo_bytes() can be incredibly slow under Windows, to the point of being unusable.  It frequently times out (>30 seconds execution time) on several Windows machines of mine.

Apparently, it's a known problem with OpenSSL (not PHP specifically).

See: http://www.google.com/search?q=openssl_random_pseudo_bytes+slow
up
13
christophe dot weis at statec dot etat dot lu
6 years ago
Another replacement for rand() using OpenSSL.

Note that a solution where the result is truncated using the modulo operator ( % ) is not cryptographically secure, as the generated numbers are not equally distributed, i.e. some numbers may occur more often than others.

A better solution than using the modulo operator is to drop the result if it is too large and generate a new one.

<?php
function crypto_rand_secure($min, $max) {
       
$range = $max - $min;
        if (
$range == 0) return $min; // not so random...
       
$log = log($range, 2);
       
$bytes = (int) ($log / 8) + 1; // length in bytes
       
$bits = (int) $log + 1; // length in bits
       
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
       
do {
           
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes, $s)));
           
$rnd = $rnd & $filter; // discard irrelevant bits
       
} while ($rnd >= $range);
        return
$min + $rnd;
}
?>
up
6
Tyler Larson
8 years ago
If you don't have this function but you do have OpenSSL installed, you can always fake it:

<?php
   
function openssl_random_pseudo_bytes($length) {
       
$length_n = (int) $length; // shell injection is no fun
       
$handle = popen("/usr/bin/openssl rand $length_n", "r");
       
$data = stream_get_contents($handle);
       
pclose($handle);
        return
$data;
    }
?>
up
1
crrodriguez at opensuse dot org
6 years ago
Remember to request at very least 8 bytes of entropy, ideally 32 or 64, to avoid possible theorical bruteforce attacks.
up
1
umairkhi at hotmail dot com
10 days ago
After the fix of insecure number generation here:

http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-8867

This function as well as the text here needs an update. I believe this function is safe to use in FIPS compliant apps as well as it now used RAND_bytes instead of  the insecure RAND_pseudo_bytes().
up
-1
Karsey
1 month ago
Why does bin2hex return twice as many characters as bytes?
up
-1
Anonymous
5 years ago
Another way to get random 32bit ints:
function myRand($max){
    do{
        $result = floor($max*(hexdec(bin2hex(openssl_random_pseudo_bytes(4)))/0xffffffff));
    }while($result == $max);
    return $result;
}
To Top