簡介亂數
今天將會是密碼學最後一個常見的主題:亂數。
分類
亂數的隨機性有三個參考標準:
- 統計學偽隨機性,看起來很亂,而且取樣極大的時候,分布是平均的。但產生的過程有規則,因此只要取得夠多樣本,就有機會推算下一個亂數為何。
- 密碼學安全偽隨機性,當有一部分的樣本與演算法時,依然無法推測下一個亂數為何。
- 真隨機性,隨機樣本無法重現,是完全不可預測的亂數。
依上述三個標準會有三種隨機數產生器
- 僞隨機數產生器(PRNG,全名為 Pseudo-random Number Generator):滿足第一個條件的隨機數。
- 密碼學安全的僞隨機數(CSPRNG,全名為 Cryptographically Secure Pseudo-random Number Generator):同時滿足前兩個條件的隨機數。
- 真隨機數(TRNG,全名為 True Random Number Generator):同時滿足三個條件的隨機數。
在一般應用上,偽隨機數就夠用了。但如果要考慮到安全議題的話,只能選擇密碼學安全的僞隨機數或真隨機數。像產生臨時金鑰即會用亂數,若亂數可被攻擊者推測的話,代表金鑰內容能被攻擊者推測出來,所有密碼防護功能就會完全沒有意義。
亂數在身分驗證上,應用場景非常多,除了剛剛提到的臨時金鑰外,像一次性密碼(OTP)、CBC 的初始向量、CSRF Token、Session Identifier 等,非常多場景會需要用到亂數產生器,因此亂數有沒有密碼學安全是非常重要。
偽隨機數的風險
參考維基百科上的資料,蠻多都很難理解,因此最終選擇了一個最好懂的來說明。
RSA 加密演算法的核心原理是兩個極大的質數相乘容易,分解困難的性質來設計的,而公鑰的設計則是可以安心的對外散佈。今天有兩把公鑰分別是 n = pq 與 *n’ = p’q’*。若偽隨機數產生的質數剛好發生 *p = p’*,這時想從 n 與 n’ 拆出 p 是非常容易的--使用輾轉相除法取因數即可,這時要再拿 q 或 q’ 就不是問題了。
RSA 是個很簡單的例子,讓大家可以理解偽隨機數會有安全性上的問題。所以安全上若有考量,則一定得使用 CSPRNG。
PHP 上的實作
在 PHP 5 之前,只有 PRNG,直到 PHP 7 開始才有 CSPRNG,裡面包含了兩個函式:random_bytes()
與 random_int()
。
而 PHP 5 可以使用 openssl_random_pseudo_bytes()
或是使用 paragonie/random_compat
這個套件做 polyfill。
小結
密碼學的介紹到此告一段落,因對此領域不熟,每天的內容都少的可憐,有機會要來好好補充這個領域的知識了。