PHP中的隨機性 你覺得自己幸運嗎?
本文分析了生成用于加密的隨機數(shù)的相關(guān)問題。 PHP 5沒有提供一種簡單的機制來生成密碼學(xué)上強壯的隨機數(shù),但是PHP 7通過引入幾個CSPRNG函數(shù)來解決了這個問題。
一、什么是CSPRNG
引用維基百科,一個密碼學(xué)上安全的偽隨機數(shù)發(fā)生器(Cryptographically Secure Pseudorandom Number Generator 縮寫CSPRNG)是一個偽隨機數(shù)生成器(PRNG),其生成的偽隨機數(shù)適用于密碼學(xué)算法。
CSPRNG可能主要用于:
- 密鑰生成(例如,生成復(fù)雜的密鑰)
- 為新用戶產(chǎn)生隨機的密碼
- 加密系統(tǒng)
獲得高級別安全性的一個關(guān)鍵方面就是高品質(zhì)的隨機性
二、PHP7 中的CSPRNG
PHP 7引入了兩個新函數(shù)可以用來實現(xiàn)CSPRNG: random_bytes 和 random_int。
random_bytes 函數(shù)返回一個字符串,接受一個int型入?yún)⒋矸祷亟Y(jié)果的字節(jié)數(shù)。
例子:
$bytes = random_bytes('10'); var_dump(bin2hex($bytes)); //possible ouput: string(20) "7dfab0af960d359388e6"
random_int 函數(shù)返回一個指定范圍內(nèi)的int型數(shù)字。
例子:
var_dump(random_int(1, 100)); //possible output: 27
三、后臺運行環(huán)境
以上函數(shù)的隨機性不同的取決于環(huán)境:
- 在window上,CryptGenRandom()總是被使用。
- 在其他平臺,arc4random_buf()如果可用會被使用(在BSD系列或者具有l(wèi)ibbsd的系統(tǒng)上成立)
- 以上都不成立的話,一個linux系統(tǒng)調(diào)用getrandom(2)會被使用。
- 如果還不行,/dev/urandom 會被作為最后一個可使用的工具
- 如果以上都不行,系統(tǒng)會拋出錯誤
四、一個簡單的測試
一個好的隨機數(shù)生成系統(tǒng)保證合適的產(chǎn)生“質(zhì)量”。為了檢查這個質(zhì)量, 通常要執(zhí)行一連串的統(tǒng)計測試。不需要深入研究復(fù)雜的統(tǒng)計主題,比較一個已知的行為和數(shù)字生成器的結(jié)果可以幫助質(zhì)量評價。
一個簡單的測試是骰子游戲。假設(shè)擲1個骰子1次得到結(jié)果為6的概率是1/6,那么如果我同時擲3個骰子100次,得到的結(jié)果粗略如下:
0 個6 = 57.9 次
1 個6 = 34.7次
2 個6 = 6.9次
3 個6 = 0.5次
以下是是實現(xiàn)實現(xiàn)擲骰子1,000,000次的代碼:
$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);
用PHP7 的 random_int 和簡單的 rand 函數(shù)可能得到如下結(jié)果
如果先看到rand 和 random_int 更好的比較我們可以應(yīng)用一個公式把結(jié)果畫在圖上。公式是:(php結(jié)果-期待的結(jié)果)/期待結(jié)果的0.5次方。
結(jié)果圖如下:
(接近0的值更好)
盡管3個6的結(jié)果表現(xiàn)不好,并且這個測試對實際應(yīng)用來說太過簡單我們?nèi)钥梢钥闯?random_int 表現(xiàn)優(yōu)于 rand.
進(jìn)一步,我們的應(yīng)用的安全級別由于不可預(yù)測性和隨機數(shù)發(fā)生器的可重復(fù)行為而得到提升。
PHP5 呢
缺省情況下,PHP5 不提供強壯的隨機數(shù)發(fā)生器。實際上,還是有選擇的比如 openssl_random_pseudo_bytes(), mcrypt_create_iv() 或者直接使用fread()函數(shù)來使用 /dev/random 或 /dev/urandom 設(shè)備。也有一些包比如 RandomLib 或 libsodium.
如果你想要開始使用一個更好的隨機數(shù)發(fā)生器并且同時準(zhǔn)備好使用PHP7,你可以使用Paragon Initiative Enterprises random_compat 庫。 random_compat 庫允許你在 PHP 5.x project.使用 random_bytes() and 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 庫和PHP7使用不同的順序:
fread() /dev/urandom if available mcrypt_create_iv($bytes, MCRYPT_CREATE_IV) COM('CAPICOM.Utilities.1')->GetRandom() openssl_random_pseudo_bytes()
這個庫的一個簡單應(yīng)用用來產(chǎn)生密碼:
$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
總結(jié)
你總是應(yīng)該使用一個密碼學(xué)上安全的偽隨機數(shù)生成器,random_compat 庫提供了一種好的實現(xiàn)。
如果你想要使用可靠的隨機數(shù)據(jù)源,如你在本文所見,建議盡快使用 random_int 和 random_bytes。
以上就是關(guān)于php隨機性的相關(guān)內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
php的instanceof和判斷閉包Closure操作示例
這篇文章主要介紹了php的instanceof和判斷閉包Closure操作,結(jié)合實例形式分析了PHP使用instanceof判斷類實例以及判斷閉包Closure相關(guān)操作技巧,需要的朋友可以參考下2020-01-01laravel 實現(xiàn)設(shè)置時區(qū)的簡單方法
今天小編就為大家分享一篇laravel 實現(xiàn)設(shè)置時區(qū)的簡單方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-10-10php數(shù)組函數(shù)序列之end() - 移動數(shù)組內(nèi)部指針到最后一個元素,并返回該元素的值
end() 函數(shù)將數(shù)組內(nèi)部指針指向最后一個元素,并返回該元素的值(如果成功)。2011-10-10php使用Swoole與WebSocket實現(xiàn)彈幕效果的示例代碼
在本文中,我們將深入探討如何使用Swoole與WebSocket結(jié)合,實現(xiàn)彈幕效果,并著重強調(diào)需要注意的關(guān)鍵地方,以確保我們的彈幕系統(tǒng)能夠高效、穩(wěn)定地運行,感興趣的朋友可以參考下2024-02-02PHP排序算法之基數(shù)排序(Radix Sort)實例詳解
這篇文章主要介紹了PHP排序算法之基數(shù)排序(Radix Sort),結(jié)合實例形式詳細(xì)分析了php基數(shù)排序算法的原理、實現(xiàn)方法與相關(guān)使用技巧,需要的朋友可以參考下2018-04-04