隨機數在 PHP 開發中無處不在,從簡單的驗證碼、隨機推薦文章,到複雜的加密演算法、負載均衡策略,皆仰賴隨機數的品質與效能。本文將系統梳理 PHP 隨機數的生成函數、特性差異,並探討實務應用場景與安全性考量。
| 函數 | PHP 版本 | 隨機來源 | 密碼學安全 | 效能 | 適用場景 |
|---|---|---|---|---|---|
rand() |
>= 4 | 系統 C library (LCG) | 否 | 快 | 一般非安全需求(如隨機顯示、遊戲邏輯) |
mt_rand() |
>= 4 | Mersenne Twister | 否 | 極快 | 高效能非安全需求(大量隨機取樣、模擬) |
random_int() |
>= 7.0 | OS CSPRNG (/dev/urandom, CryptGenRandom) | 是 | 中 | 密碼學安全需求(Token、金鑰、密碼重設碼) |
random_bytes() |
>= 7.0 | OS CSPRNG | 是 | 中 | 生成二進位隨機資料(IV、Salt、API Key) |
openssl_random_pseudo_bytes() |
>= 5.3 (需 OpenSSL) | OpenSSL CSPRNG | 是 | 較慢 | 舊版 PHP 相容性需求的安全隨機 |
$code = mt_rand(100000, 999999);
$token = bin2hex(random_bytes(32)); // 64 字元十六進位字串
$items = ['a', 'b', 'c', 'd', 'e'];
$count = 3;
$keys = array_rand($items, $count);
$result = array_intersect_key($items, array_flip($keys));
function weightedRandom(array $weights) {
$total = array_sum($weights);
$rand = mt_rand(1, $total);
$accum = 0;
foreach ($weights as $key => $weight) {
$accum += $weight;
if ($rand <= $accum) {
return $key;
}
}
}
// 用法:['grand_prize' => 1, 'first_prize' => 5, 'consolation' => 100]
rand() / mt_rand() 產生密碼、Token、Session ID、加密金鑰,其輸出可預測,易遭暴力破解。random_int() / random_bytes(),並捕獲 Exception 處理熵源不足情況。openssl_random_pseudo_bytes() 並檢查第二參數 $crypto_strong 為 true。mt_srand() 僅供測試複現用途,生產環境切勿手動設定種子,讓 PHP 自動從高熵源初始化。mt_rand() 比 rand() 快 4 倍以上。random_bytes($n * 32) 再切割,比迴圈呼叫 random_bytes(32) 快得多(減少系統呼叫開銷)。理解 PHP 各隨機函數的底層機制與安全層級,是寫出健壯、安全程式的基石。請根據業務安全等級選擇適當函數,並養成「預設安全」的開發習慣:除非確定不涉及安全,優先採用 CSPRNG 系列函數。