2014年5月30日 星期五

安全的 PRNG(亂數產生器)

最近公司引入了一個原始碼掃描的系統 Fortify,在掃描的結果中回報了我們的專案使用了一些 java.util.Random 這個亂數產生器
而這個亂數產生器在亟需安全的環境中並不安全,因為它並不是屬於加密安全(cryptographically secure)的亂數產生器
因此產生的結果很容易被預測。

簡單地查詢了一下,Fortify 官方網站中有關於這個問題的描述 [1],節錄內容如下。
PRNG包括兩種類型:統計式和加密式。統計式PRNG可提供有用的統計內容,但是它們的輸出很容易預測,因此很容易複製數值串流,因此不適用於安全性取決於所產生數值的不可預測性的環境。加密式PRNG則會藉由產生更難以預測的輸出來處理這個問題。為了讓加密數值更加安全,必須使攻擊者無法或很難區別此加密數值和真實的亂數值。一般來說,如果沒有指出某個PRNG演算法經過加密保護,那麼它很可能是一個統計型PRNG,所以不應該在安全性要求較高的環境中使用。

在 Java 中,加密式的 PRNG 大概就是 java.security.SecureRandom [2] 了。
在查詢的過程中,也查到一個有趣的相關討論 [3]
發問的網友 user967973 詢問說如果使用 java.security.SecureRandom 產生的亂數作為 java.util.Random 的種子,是不是 java.util.Random 就算是安全的?
結果當然不是,網友 emboss 回應因為攻擊者是可以透過收集產生的結果去推測種子。
另外根據 emboss 提供的一份網路上的實驗顯示,需要收集的結果僅僅 2 個值(這數字還真是太驚人了....)就足以大幅降低攻擊複雜度!

因此總結來說,如果亂數產生器產生的亂數是很重要的系統安全的一環時,請使用 java.security.SecureRandom 來代替 java.util.Random 吧!

參考資料:
1、Insecure Randomness
2、java.security.SecureRandom
3、Difference between java.util.Random and java.security.SecureRandom
4、Cracking Random Number Generators

沒有留言: