PHP中的随机性——你觉得自己幸运吗?
本文分析了生成用于加密的隨機(jī)數(shù)的相關(guān)問(wèn)題。?PHP?5沒(méi)有提供一種簡(jiǎn)單的機(jī)制來(lái)生成密碼學(xué)上強(qiáng)壯的隨機(jī)數(shù),但是PHP?7通過(guò)引入幾個(gè)CSPRNG函數(shù)來(lái)解決了這個(gè)問(wèn)題。
什么是CSPRNG
引用維基百科,一個(gè)密碼學(xué)上安全的偽隨機(jī)數(shù)發(fā)生器(Cryptographically?Secure?Pseudorandom?Number?Generator?縮寫(xiě)CSPRNG)是一個(gè)偽隨機(jī)數(shù)生成器(PRNG),其生成的偽隨機(jī)數(shù)適用于密碼學(xué)算法。
CSPRNG可能主要用于:
-
密鑰生成(例如,生成復(fù)雜的密鑰)
-
為新用戶產(chǎn)生隨機(jī)的密碼
-
加密系統(tǒng)
獲得高級(jí)別安全性的一個(gè)關(guān)鍵方面就是高品質(zhì)的隨機(jī)性
PHP7?中的CSPRNG
PHP?7引入了兩個(gè)新函數(shù)可以用來(lái)實(shí)現(xiàn)CSPRNG:?random_bytes?和?random_int。
random_bytes?函數(shù)返回一個(gè)字符串,接受一個(gè)int型入?yún)⒋矸祷亟Y(jié)果的字節(jié)數(shù)。
例子:
random_int?函數(shù)返回一個(gè)指定范圍內(nèi)的int型數(shù)字。
例子:
后臺(tái)運(yùn)行環(huán)境
以上函數(shù)的隨機(jī)性不同的取決于環(huán)境:
-
在window上,CryptGenRandom()總是被使用。
-
在其他平臺(tái),arc4random_buf()如果可用會(huì)被使用(在BSD系列或者具有l(wèi)ibbsd的系統(tǒng)上成立)
-
以上都不成立的話,一個(gè)linux系統(tǒng)調(diào)用getrandom(2)會(huì)被使用。
-
如果還不行,/dev/urandom?會(huì)被作為最后一個(gè)可使用的工具
-
如果以上都不行,系統(tǒng)會(huì)拋出錯(cuò)誤
一個(gè)簡(jiǎn)單的測(cè)試
一個(gè)好的隨機(jī)數(shù)生成系統(tǒng)保證合適的產(chǎn)生“質(zhì)量”。為了檢查這個(gè)質(zhì)量,?通常要執(zhí)行一連串的統(tǒng)計(jì)測(cè)試。不需要深入研究復(fù)雜的統(tǒng)計(jì)主題,比較一個(gè)已知的行為和數(shù)字生成器的結(jié)果可以幫助質(zhì)量評(píng)價(jià)。
一個(gè)簡(jiǎn)單的測(cè)試是骰子游戲。假設(shè)擲1個(gè)骰子1次得到結(jié)果為6的概率是1/6,那么如果我同時(shí)擲3個(gè)骰子100次,得到的結(jié)果粗略如下:
-
0?個(gè)6?=?57.9?次
-
1?個(gè)6?=?34.7次
-
2?個(gè)6?=?6.9次
-
3?個(gè)6?=?0.5次
以下是是實(shí)現(xiàn)實(shí)現(xiàn)擲骰子1,000,000次的代碼:
用PHP7?的?random_int?和簡(jiǎn)單的?rand?函數(shù)可能得到如下結(jié)果
| Sixes | expected | random_int |
| 0 | 579000 | 579430 |
| 1 | 347000 | 346927 |
| 2 | 69000 | 68985 |
| 3 | 5000 | 4658 |
如果先看到rand?和?random_int?更好的比較我們可以應(yīng)用一個(gè)公式把結(jié)果畫(huà)在圖上。公式是:(php結(jié)果-期待的結(jié)果)/期待結(jié)果的0.5次方。
結(jié)果圖如下:
(接近0的值更好)
盡管3個(gè)6的結(jié)果表現(xiàn)不好,并且這個(gè)測(cè)試對(duì)實(shí)際應(yīng)用來(lái)說(shuō)太過(guò)簡(jiǎn)單我們?nèi)钥梢钥闯?random_int?表現(xiàn)優(yōu)于?rand.
進(jìn)一步,我們的應(yīng)用的安全級(jí)別由于不可預(yù)測(cè)性和隨機(jī)數(shù)發(fā)生器的可重復(fù)行為而得到提升。
PHP5?呢
缺省情況下,PHP5?不提供強(qiáng)壯的隨機(jī)數(shù)發(fā)生器。實(shí)際上,還是有選擇的比如?openssl_random_pseudo_bytes(),?mcrypt_create_iv()?或者直接使用fread()函數(shù)來(lái)使用?/dev/random?或?/dev/urandom?設(shè)備。也有一些包比如?RandomLib?或?libsodium.
如果你想要開(kāi)始使用一個(gè)更好的隨機(jī)數(shù)發(fā)生器并且同時(shí)準(zhǔn)備好使用PHP7,你可以使用Paragon?Initiative?Enterprises?random_compat?庫(kù)。?random_compat?庫(kù)允許你在?PHP?5.x?project.使用?random_bytes()?and?random_int()
這個(gè)庫(kù)可以通過(guò)Composer安裝:
random_compat?庫(kù)和PHP7使用不同的順序:
想知道為什么是這個(gè)順序建議閱讀?documentation.
這個(gè)庫(kù)的一個(gè)簡(jiǎn)單應(yīng)用用來(lái)產(chǎn)生密碼:
總結(jié)
你總是應(yīng)該使用一個(gè)密碼學(xué)上安全的偽隨機(jī)數(shù)生成器,random_compat?庫(kù)提供了一種好的實(shí)現(xiàn)。
如果你想要使用可靠的隨機(jī)數(shù)據(jù)源,如你在本文所見(jiàn),建議盡快使用?random_int?和?random_bytes.
作者:邱康
來(lái)源:51CTO
總結(jié)
以上是生活随笔為你收集整理的PHP中的随机性——你觉得自己幸运吗?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 美国国防部CIO:企业IT可考虑用开源做
- 下一篇: 在PHP中使用CURL,“撩”服务器只需