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型入參代表返回結果的字節數。
例子:
random_int?函數返回一個指定范圍內的int型數字。
例子:
后臺運行環境
以上函數的隨機性不同的取決于環境:
-
在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次的代碼:
用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安裝:
random_compat?庫和PHP7使用不同的順序:
想知道為什么是這個順序建議閱讀?documentation.
這個庫的一個簡單應用用來產生密碼:
總結
你總是應該使用一個密碼學上安全的偽隨機數生成器,random_compat?庫提供了一種好的實現。
如果你想要使用可靠的隨機數據源,如你在本文所見,建議盡快使用?random_int?和?random_bytes.
作者:邱康
來源:51CTO
總結
以上是生活随笔為你收集整理的PHP中的随机性——你觉得自己幸运吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 美国国防部CIO:企业IT可考虑用开源做
- 下一篇: 在PHP中使用CURL,“撩”服务器只需