我們真的應該僅僅依靠“密碼安全偽隨機數生成器”(CSPRNG)來保證安全的隨機輸出嗎?
例如,在客戶端 JavaScript 中使用 CSPRNG 時,將隨機數散列隨機次數是否會過度設計?(假設這不是最強的 CSPRNG)
編輯:或者當安全性在使用客戶端 JavaScript 的情況下極其重要時,依賴更多的隨機設備(如混合/散列客戶端安全隨機 + 伺服器安全隨機)是否明智/必要,因為網路客戶端/瀏覽器/代理未知?
我們真的應該僅僅依靠“密碼安全偽隨機數生成器”(CSPRNG)來保證安全的隨機輸出嗎?
不,我們不應該僅僅依靠 CSPRNG來獲得安全的隨機輸出。對於此任務,CSPRNG 需要真正(非偽)隨機輸入(種子)。缺少這一點,重用相同種子的相同 CSPRNG 的不同實例將在重置時生成相同的輸出(例如,再次執行程序,重置設備)。使用沒有隨機性或隨機性不足的 CSPRNG 是最經典的安全妥協來源;參見例如探勘你的 Ps 和 Qs:檢測網路設備中廣泛存在的弱密鑰。
例如,在客戶端 JavaScript 中使用 CSPRNG 時,對隨機數進行隨機次數的雜湊處理是否會過度設計?
是的,所提議的是經過深思熟慮的過度設計。
“偽”(CSPRNG 和 PRNG 中的 P)意味著在沒有變數輸入的情況下提供從執行到執行的可重複結果。如果我們使用 (CS)PRNG 來決定自己執行多少次,它仍然是 (CS)PRNG。上面討論的問題沒有得到解決,甚至沒有得到有意義的緩解。我們對額外的安全性產生了錯誤的印象。
更好的方法是在 CSPRNG 的輸入端混合多個隨機源,並使用該 CSPRNG。在客戶端 JavaScript 中,源可以是系統提供的希望為真的 RNG(
Math.random()
如果沒有更好的可用),游標位置和系統時間在由網路或使用者界面事件(按鍵)確定的不同時刻採樣,伺服器提供的隨機數,作為最後的鍵盤輸入。CSPRNG 可以由散列函式建構。這是否過度設計取決於安全目標、威脅模型和執行時環境。後者在編寫程式碼時通常是未知的。許多瀏覽器在其歷史上的某個時刻不安全
Math.random()
並且沒有提供安全的替代方案,因此恕我直言,這種預防措施聽起來很合理。更新以下評論
使用散列(CSPRNG 輸出、可用客戶端數據、可用伺服器數據)會比僅使用 CSPRNG 提供更多安全性嗎?
是的,如果這三個條件成立:
- 雜湊對於現代定義是安全的(類似於 PRF)。
- 並且“CSPRNG 輸出”中的明顯熵(對於不知道它的秘密種子的人)至少是散列的寬度;例如,如果這個輸出是 $ n $ 十進制數字, $ n\log_2(10) $ 位。
- 並且至少有大約 1 位的額外數據輸入對於對手來說是不可預測的。如果沒有這個條件,輸出中的熵可以減少 0.83 位(參見this),這可能是一個(通常非常小)的問題。
這對於抗碰撞或抗原像的雜湊太窄(例如 SHA-256 被截斷為 80 位)有效,並且如果我們用任何可用的 RNG 替換“CSPRNG”,它仍然有效。有更好的方法來組合額外的熵,但那已經是一個值得改進的方法。