PHP 中的隨機數——你覺得可靠麼?
本文主要分析以加密為目的的隨機數生成問題。PHP 5 並未提供生成強加密隨機數的簡便機制,但是,PHP 7 引入了兩個 CSPRNG 函式以解決該問題。系 OneAPM 工程師編譯整理。
什麼是 CSPRNG?
引用維基百科的定義,密碼安全的虛擬隨機數生成器(Cryptographically Secure Pseudorandom Number Generator,CSPRNG)是帶有特定屬性使之在密碼學中適用的虛擬隨機數生成器(pseudo-random number generator,PRNG)。
CSPRNG 主要用於:
- 生成鍵(比如:生成複雜的鍵)
- 為新的使用者賬號生成隨機密碼
- 加密系統
保證高安全水準的一個重要因素便是高質量的隨機數。
PHP 7 中的 CSPRNG
PHP 7 為 CSPRNG 引入了兩種新函式:random_bytes
與 random_int
。
random_bytes
函式返回 string
型別,並接受一個 int
型別為引數,該引數規定了所返回字串的位元組長度。
例如:
$bytes = random_bytes('10');
var_dump(bin2hex($bytes));
//possible ouput: string(20) "7dfab0af960d359388e6"
random_int
函式返回給定範圍內的整型數字。
舉例:
var_dump(random_int(1, 100));
//possible output: 27
幕後解密
以上函式的隨機數來源因環境不同而有所差異:
- 在 Windows 系統,會使用
CryptGenRandom()
函式。 - 在其他平臺,會優先使用
arc4random_buf()
函式(限 BSD 衍生系統或帶 libbsd 的系統)。 - 若以上兩點均不符合,會使用 Linux [getrandom(2)](http://man7.org/linux/man-pages/man2/ getrandom.2.html) 系統呼叫。
- 若以上來源均不符合,會丟擲
Error
。
一個簡例
一個好的隨機數生成系統能確保生成質量適合的隨機數。為了檢驗質量,需要執行一系列的統計試驗。此處,暫不深入討論複雜的統計話題,將已知的行為與隨機數生成器的結果進行比較,有助於質量評估。
一個簡單的測試方法是擲骰遊戲。假設投擲一次,投出6的概率是1/6。如果同時投擲三個骰子,投100次,投得零次、一次、兩次及三次6的次數大概是:
- 0 次6 = 57.9 次
- 1 次6 = 34.7 次
- 2 次6 = 6.9 次
- 3 次6 = 0.5 次
以下是骰子投擲100萬次的程式碼:
$times = 1000000;
$result = [];
for ($i=0; $i<$times; $i++){
$dieRoll = array(6 => 0); //initializes just the six counting to zero
$dieRoll[roll()] += 1; //first die
$dieRoll[roll()] += 1; //second die
$dieRoll[roll()] += 1; //third die
$result[$dieRoll[6]] += 1; //counts the sixes
}
function roll(){
return random_int(1,6);
}
var_dump($result);
用 PHP 7 的 random_int
與簡單的 rand
函式測試上面的程式碼,可能會得到:
Sixes | expected | random_int | rand |
---|---|---|---|
0 | 579000 | 579430 | 578179 |
1 | 347000 | 346927 | 347620 |
2 | 69000 | 68985 | 69586 |
3 | 5000 | 4658 | 4615 |
更直觀地檢視 rand
與 random_int
的差別,可以運用方程式放大兩組結果的差異,並繪製成圖表:
php result - expected result / sqrt(expected)
得到的結果如下:
(結果越接近零越好)
即便三個6的組合表現一般,且該測試與真實應用相比太過簡單,我們也能清楚地看到 random_int
的表現優於 rand
。況且,隨機數生成器的可預見行為、重複行為越少,應用的安全程度就更高。
PHP 5 又如何呢?
預設情況下,PHP 5 並未提供任何強虛擬隨機數生成器。而實際使用中,可以使用 openssl_random_pseudo_bytes()
、mcrypt_create_iv()
方法,或直接結合使用 /dev/random
或 /dev/urandom
與 fread()
方法。此外,還有包 RandomLib 或 libsodium。
如果你想用一個比較好的隨機數生成器,同時能與 PHP 7 相容,你可以使用 Paragon Initiative 公司的 random_compat
庫。該庫允許在 PHP 5.x 專案中使用 random_bytes()
與 random_int()
方法。
該庫可以使用 Composer 進行安裝:
composer require paragonie/random_compat
require 'vendor/autoload.php';
$string = random_bytes(32);
var_dump(bin2hex($string));
// string(64) "8757a27ce421b3b9363b7825104f8bc8cf27c4c3036573e5f0d4a91ad2aaec6f"
$int = random_int(0,255);
var_dump($int);
// int(81)
該 random_compat
庫使用了與 PHP 7 中不同的優先序列:
- 如果可用,先使用 fread() /dev/urandom
- mcrypt_create_iv($bytes, MCRYPT_CREATE_IV)
- COM('CAPICOM.Utilities.1')->GetRandom()
- openssl_random_pseudo_bytes()
想了解為何採用這一優先序列,可以閱讀本文件。
使用該庫生成密碼的簡單案例如下:
$passwordChar = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$passwordLength = 8;
$max = strlen($passwordChar) - 1;
$password = '';
for ($i = 0; $i < $passwordLength; ++$i) {
$password .= $passwordChar[random_int(0, $max)];
}
echo $password;
//possible output: 7rgG8GHu
總結
你應該儘量使用在密碼學上安全的虛擬隨機數生成器。random_compat
庫為此提供了很好的實現方法。
如果你想使用可靠的隨機數來源,正如前文所述,儘快開始使用 random_int
與 random_bytes
吧!
原文地址:http://www.sitepoint.com/randomness-php-feel-lucky/
OneAPM for PHP 能夠深入到所有 PHP 應用內部完成應用效能管理 能夠深入到所有 PHP 應用內部完成應用效能管理和監控,包括程式碼級別效能問題的可見性、效能瓶頸的快速識別與追溯、真實使用者體驗監控、伺服器監控和端到端的應用效能管理。想閱讀更多技術文章,請訪問 OneAPM 官方技術部落格。
相關文章
- 熵不起得隨機數熵隨機
- GoLang 中的隨機數 tipsGolang隨機
- 你覺得你每天最佳的工作時間是什麼時候?
- 你覺得程式設計師最大的悲哀是什麼?程式設計師
- 區塊鏈中的隨機數區塊鏈隨機
- 為什麼你總是覺得被割韭菜?
- php生成一個可選位數的隨機碼PHP隨機
- PHP實現隨機數字、字母的驗證碼功能PHP隨機
- 你覺得大模型時代該出現什麼?大模型
- 偽隨機數是什麼?偽隨機數生成方法有哪些?隨機
- Python中如何生成隨機數?Python隨機
- 明明的隨機數隨機
- 說說你做過讓你覺得最滿意的專案是什麼?為什麼?
- 怎麼用Python生成隨機數Python隨機
- 你覺得你的測試水平怎麼樣,在市場上是一個什麼樣的水平。
- Matlab 隨機生成兩個數值之間的隨機數Matlab隨機
- 隨機數隨機
- python生成隨機數、隨機字串Python隨機字串
- 為什麼軟體開發方法論讓你覺得糟糕
- 隨機的細胞騎士——《死亡細胞》Rougelike隨機性思路的得與失隨機
- matlab中的產生隨機數的rand函式Matlab隨機函式
- 你覺得前端有必要寫文件嗎?前端
- 你們覺得雲棲社群好用嗎?
- Python如何隨機生成1到100的隨機數?Python隨機
- python3怎麼列印隨機數Python隨機
- 為什麼我覺得Python爛的要死?Python
- PHP生成卡哇伊隨機頭像PHP隨機
- php生成唯一隨機碼PHP隨機
- 華為mate40pro引數配置曝光,你覺得值得入手嗎?
- 000.【Web安全】你所使用的隨機數真的安全嗎?Web隨機
- 隨機範圍小數和隨機範圍整數隨機
- 風場視覺化:隨機重置視覺化隨機
- Linux Shell 生成隨機數和隨機字串Linux隨機字串
- 我覺得你可能真的還不會JavaJava
- 更安全的隨機數生成隨機
- JavaScript隨機數的應用JavaScript隨機
- 淺析--為什麼軟體開發方法論讓你覺得糟糕?
- MATLAB中如何生成指定範圍的隨機整數向量Matlab隨機
- 區塊鏈100講:區塊鏈中的隨機數區塊鏈隨機