首先,說一下偽隨機數,偽隨機數並不是假隨機數,這裡的“偽”是有規律的意思,就是計算機產生的偽隨機數既是隨機的又是有規律的。怎樣理解呢?產生的偽隨機數有時遵守一定的規律,有時不遵守任何規律;偽隨機數有一部分遵守一定的規律;另一部分不遵守任何規律。比如“世上沒有兩片形狀完全相同的樹葉”。
/dev/random和/dev/urandom是Linux系統中提供的隨機偽設備,這兩個設備的任務,是提供永不為空的隨機字節數據流。很多解密程序與安全應用程序(如SSH Keys,SSL Keys等)需要它們提供的隨機數據流。
這兩個設備的差異在於:/dev/random的random pool依賴於系統中斷,因此在系統的中斷數不足時,/dev/random設備會一直封鎖,嘗試讀取的進程就會進入等待狀態,直到系統的中斷數充分夠用, /dev/random設備可以保證數據的隨機性。/dev/urandom不依賴系統的中斷,也就不會造成進程忙等待,但是數據的隨機性也不高。
代碼示例
利用mycrpt
/*
* 通過此方法獲取隨機數,但需要mycrpt支持
*
*/
private function GetURandom2($min = 0, $max = 0x7FFFFFFF)
{/*{{{*/
$diff = $max - $min;
if ($diff < 0 || $diff > 0x7FFFFFFF) {
throw new RuntimeException("Bad range");
}
$bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
if ($bytes === false || strlen($bytes) != 4) {
throw new RuntimeException("Unable to get 4 bytes");
}
$ary = unpack("Nint", $bytes);
$val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe
$fp = (float) $val / 2147483647.0; // convert to [0,1]
return round($fp * $diff) + $min;
}/*}}}*/
}
使用fread讀取/dev/urandom文件
/* *
* php 版本 >= 5.3, 通過讀取"/dev/urandom"實現產生較好隨機數
*
* */
private function GetURandom($min = 0, $max = 0x7FFFFFFF)
{/*{{{*/
$diff = $max - $min;
if ($diff > PHP_INT_MAX) {
throw new RuntimeException('Bad Range');
}
$fh = fopen('/dev/urandom', 'r');
stream_set_read_buffer($fh, PHP_INT_SIZE);
$bytes = fread($fh, PHP_INT_SIZE );
if ($bytes === false || strlen($bytes) != PHP_INT_SIZE ) {
//throw new RuntimeException("nable to get". PHP_INT_SIZE . "bytes");
return 0;
}
fclose($fh);
if (PHP_INT_SIZE == 8) { // 64-bit versions
list($higher, $lower) = array_values(unpack('N2', $bytes));
$value = $higher << 32 | $lower;
}
else { // 32-bit versions
list($value) = array_values(unpack('Nint', $bytes));
}
$val = $value & PHP_INT_MAX;
$fp = (float)$val / PHP_INT_MAX; // convert to [0,1]
return (int)(round($fp * $diff) + $min);
}/*}}}*/
*