PHP中的隨機性——你覺得自己幸運嗎?
本文由碼農網 – 邱康原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃!
本文分析了生成用於加密的隨機數的相關問題。 PHP 5沒有提供一種簡單的機制來生成密碼學上強壯的隨機數,但是PHP 7通過引入幾個CSPRNG函式來解決了這個問題。
什麼是CSPRNG
引用維基百科,一個密碼學上安全的偽隨機數發生器(Cryptographically Secure Pseudorandom Number Generator 縮寫CSPRNG)是一個偽隨機數生成器(PRNG),其生成的偽隨機數適用於密碼學演算法。
CSPRNG可能主要用於:
- 金鑰生成(例如,生成複雜的金鑰)
- 為新使用者產生隨機的密碼
- 加密系統
獲得高階別安全性的一個關鍵方面就是高品質的隨機性
PHP7 中的CSPRNG
PHP 7引入了兩個新函式可以用來實現CSPRNG: random_bytes 和 random_int。
random_bytes 函式返回一個字串,接受一個int型入參代表返回結果的位元組數。
例子:
$bytes = random_bytes('10'); var_dump(bin2hex($bytes)); //possible ouput: string(20) "7dfab0af960d359388e6"
random_int 函式返回一個指定範圍內的int型數字。
例子:
var_dump(random_int(1, 100)); //possible output: 27
後臺執行環境
以上函式的隨機性不同的取決於環境:
- 在window上,CryptGenRandom()總是被使用。
- 在其他平臺,arc4random_buf()如果可用會被使用(在BSD系列或者具有libbsd的系統上成立)
- 以上都不成立的話,一個linux系統呼叫getrandom(2)會被使用。
- 如果還不行,/dev/urandom 會被作為最後一個可使用的工具
- 如果以上都不行,系統會丟擲錯誤
一個簡單的測試
一個好的隨機數生成系統保證合適的產生“質量”。為了檢查這個質量, 通常要執行一連串的統計測試。不需要深入研究複雜的統計主題,比較一個已知的行為和數字生成器的結果可以幫助質量評價。
一個簡單的測試是骰子游戲。假設擲1個骰子1次得到結果為6的概率是1/6,那麼如果我同時擲3個骰子100次,得到的結果粗略如下:
- 0 個6 = 57.9 次
- 1 個6 = 34.7次
- 2 個6 = 6.9次
- 3 個6 = 0.5次
以下是是實現實現擲骰子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 函式可能得到如下結果
Sixes | expected | random_int |
0 | 579000 | 579430 |
1 | 347000 | 346927 |
2 | 69000 | 68985 |
3 | 5000 | 4658 |
如果先看到rand 和 random_int 更好的比較我們可以應用一個公式把結果畫在圖上。公式是:(php結果-期待的結果)/期待結果的0.5次方。
結果圖如下:
(接近0的值更好)
儘管3個6的結果表現不好,並且這個測試對實際應用來說太過簡單我們仍可以看出 random_int 表現優於 rand.
進一步,我們的應用的安全級別由於不可預測性和隨機數發生器的可重複行為而得到提升。
PHP5 呢
預設情況下,PHP5 不提供強壯的隨機數發生器。實際上,還是有選擇的比如 openssl_random_pseudo_bytes(), mcrypt_create_iv() 或者直接使用fread()函式來使用 /dev/random 或 /dev/urandom 裝置。也有一些包比如 RandomLib 或 libsodium.
如果你想要開始使用一個更好的隨機數發生器並且同時準備好使用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()
想知道為什麼是這個順序建議閱讀 documentation.
這個庫的一個簡單應用用來產生密碼:
$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.codeceo.com/article/php-random.html
英文原文:Randomness in PHP – Do You Feel Lucky?
翻譯作者:碼農網 – 邱康
[ 轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]
相關文章
- PHP 中的隨機數——你覺得可靠麼?PHP隨機
- 爛大街的 Spring 迴圈依賴問題,你覺得自己會了嗎Spring
- 專案管理心得——你為啥會覺得自己很忙?專案管理
- 年底找工作,太難了!你覺得難嗎?
- 隨機的細胞騎士——《死亡細胞》Rougelike隨機性思路的得與失隨機
- 卡牌遊戲中的隨機性(上)遊戲隨機
- #剛拿到阿里offer小夥的Java開發要求自述,你覺得你能去阿里嗎阿里Java
- CSS面試要點!看完你還覺得你已經學好CSS了嗎?CSS面試
- 犧牲速度來節省記憶體,Redis是覺得自己太快了嗎記憶體Redis
- 幸運數字
- 卡牌遊戲中的隨機性(下):使用標誌性元素遊戲隨機
- python程式程式碼這樣加密保護,你覺得可以嗎?Python加密
- 你覺得我的這段Java程式碼還有優化的空間嗎?Java優化
- php隨機字串PHP隨機字串
- 熵不起得隨機數熵隨機
- 000.【Web安全】你所使用的隨機數真的安全嗎?Web隨機
- 你真的會用 Java 中的三目運算子嗎?Java
- 前端元件,不多,只保留自己覺得適合和好用的前端元件
- PHP 生成更好的隨機數PHP隨機
- 這10條PHP7中的禁忌,你知道嗎?PHP
- 進了阿里,還是覺得自己很失敗阿里
- 幸運kuai3和值必中玩法技巧AI
- WebAssembly Demo之Canvas中隨機運動圓球WebCanvas隨機
- 計算機視覺隨談計算機視覺
- .net 運用YUI相關的dll壓縮js (按照自己的規則,想想都覺得強大和有趣)UIJS
- 【陣列】1394. 找出陣列中的幸運數(簡單)陣列
- 應屆畢業生,工作了幾個月覺得公司不合適自己,應該辭職嗎?
- “臘雞遊戲,全靠運氣”——卡牌遊戲隨機性意義探究遊戲隨機
- PHP獲取隨機數PHP隨機
- 如何介紹你的遊戲,以使玩家覺得遊戲很酷?遊戲
- 央視新聞《 幸運中彩⃞票app新版 》手機搜狐網APP
- 有隨機性,有變數,有期望,有運氣,這就是遊戲的魅力!隨機變數遊戲
- 風場視覺化:隨機重置視覺化隨機
- 學會閱讀原始碼後,我覺得自己better了原始碼
- 我覺得你可能真的還不會JavaJava
- 運用JS 實現隨機點名 (隨機點名)JS隨機
- 殺傷性機器人再現,你會害怕嗎?機器人
- 運維 + AI,你得先搞懂這些運維AI