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;
}
openssl_random_pseudo_bytes
(PHP 5 >= 5.3.0)
openssl_random_pseudo_bytes — Yarı-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
TRUEdöner. Bir hata oluşursa bu değerNULLolacaktı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)
Anonymous ¶
1 year ago
christophe dot weis at statec dot etat dot lu ¶
2 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;
}
?>
crrodriguez at opensuse dot org ¶
2 years ago
Remember to request at very least 8 bytes of entropy, ideally 32 or 64, to avoid possible theorical bruteforce attacks.
Tyler Larson ¶
3 years ago
Here's a drop-in replacement for rand() using OpenSSL as your PRNG:
<?php
function crypto_rand($min,$max) {
$range = $max - $min;
if ($range == 0) return $min; // not so random...
$length = (int) (log($range,2) / 8) + 1;
return $min + (hexdec(bin2hex(openssl_random_pseudo_bytes($length,$s))) % $range);
}
?>
Tyler Larson ¶
3 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;
}
?>
acatalept at gmail ¶
2 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
gorgo ¶
3 years ago
a simple way to generate a random password is:
<?php
$password = base64_encode(openssl_random_pseudo_bytes($length, $strong));
?>
this function generates a password with a fallback to mt_rand() if no openssl is available:
<?php
/**
* generates a random password, uses base64: 0-9a-zA-Z/+
* @param int [optional] $length length of password, default 24 (144 Bit)
* @return string password
*/
function generatePassword($length = 24) {
if(function_exists('openssl_random_pseudo_bytes')) {
$password = base64_encode(openssl_random_pseudo_bytes($length, $strong));
if($strong == TRUE)
return substr($password, 0, $length); //base64 is about 33% longer, so we need to truncate the result
}
//fallback to mt_rand if php < 5.3 or no openssl available
$characters = '0123456789';
$characters .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz/+';
$charactersLength = strlen($characters)-1;
$password = '';
//select some random characters
for ($i = 0; $i < $length; $i++) {
$password .= $characters[mt_rand(0, $charactersLength)];
}
return $password;
}
?>
note: openssl_random_pseudo_bytes() is considerably slower than mt_rand.
