簡介亂數

今天將會是密碼學最後一個常見的主題:亂數。

分類

亂數的隨機性有三個參考標準:

  1. 統計學偽隨機性,看起來很亂,而且取樣極大的時候,分布是平均的。但產生的過程有規則,因此只要取得夠多樣本,就有機會推算下一個亂數為何。
  2. 密碼學安全偽隨機性,當有一部分的樣本與演算法時,依然無法推測下一個亂數為何。
  3. 真隨機性,隨機樣本無法重現,是完全不可預測的亂數。

依上述三個標準會有三種隨機數產生器

  1. 僞隨機數產生器(PRNG,全名為 Pseudo-random Number Generator:滿足第一個條件的隨機數。
  2. 密碼學安全的僞隨機數(CSPRNG,全名為 Cryptographically Secure Pseudo-random Number Generator:同時滿足前兩個條件的隨機數。
  3. 真隨機數(TRNG,全名為 True Random Number Generator:同時滿足三個條件的隨機數。

在一般應用上,偽隨機數就夠用了。但如果要考慮到安全議題的話,只能選擇密碼學安全的僞隨機數或真隨機數。像產生臨時金鑰即會用亂數,若亂數可被攻擊者推測的話,代表金鑰內容能被攻擊者推測出來,所有密碼防護功能就會完全沒有意義。

亂數在身分驗證上,應用場景非常多,除了剛剛提到的臨時金鑰外,像一次性密碼(OTP)、CBC 的初始向量、CSRF Token、Session Identifier 等,非常多場景會需要用到亂數產生器,因此亂數有沒有密碼學安全是非常重要。

偽隨機數的風險

參考維基百科上的資料,蠻多都很難理解,因此最終選擇了一個最好懂的來說明。

RSA 加密演算法的核心原理是兩個極大的質數相乘容易,分解困難的性質來設計的,而公鑰的設計則是可以安心的對外散佈。今天有兩把公鑰分別是 n = pq 與 *n’ = p’q’*。若偽隨機數產生的質數剛好發生 *p = p’*,這時想從 nn’ 拆出 p 是非常容易的--使用輾轉相除法取因數即可,這時要再拿 qq’ 就不是問題了。

RSA 是個很簡單的例子,讓大家可以理解偽隨機數會有安全性上的問題。所以安全上若有考量,則一定得使用 CSPRNG。

PHP 上的實作

在 PHP 5 之前,只有 PRNG,直到 PHP 7 開始才有 CSPRNG,裡面包含了兩個函式:random_bytes()random_int()

而 PHP 5 可以使用 openssl_random_pseudo_bytes() 或是使用 paragonie/random_compat 這個套件做 polyfill。

小結

密碼學的介紹到此告一段落,因對此領域不熟,每天的內容都少的可憐,有機會要來好好補充這個領域的知識了。

參考資料