歡迎光臨
每天分享高質量文章

如何安全地生成隨機數 | Linux 中國

太長了,懶得看:直接使用 urandom 吧。
— Thomas & Erin Ptacek


致謝
編譯自 | https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ 
 作者 | Thomas & Erin Ptacek
 譯者 | kimii ? ? 共計翻譯:8 篇 貢獻時間:117 天

使用 urandom

使用 urandom[1]!使用 urandom[2]!使用 urandom[3]

使用 urandom[4]!使用 urandom[5]!使用 urandom[6]

但對於密碼學金鑰呢?

仍然使用 urandom[6]

為什麼不是 SecureRandom、OpenSSL、havaged 或者 c 語言實現呢?

這些是使用者空間的 CSPRNG(偽隨機數生成器)。你應該用內核的 CSPRNG,因為:

◈ 內核可以訪問原始裝置熵。
◈ 它可以確保不在應用程式之間共享相同的狀態。
◈ 一個好的核心 CSPRNG,像 FreeBSD 中的,也可以保證它播種之前不給你隨機資料。

研究過去十年中的隨機失敗案例,你會看到一連串的使用者空間的隨機失敗案例。Debian 的 OpenSSH 崩潰[7]?使用者空間隨機!安卓的比特幣錢包重覆 ECDSA 隨機 k 值[8]?使用者空間隨機!可預測洗牌的賭博網站?使用者空間隨機!

使用者空間的生成器幾乎總是依賴於內核的生成器。即使它們不這樣做,整個系統的安全性也會確保如此。但使用者空間的 CSPRNG 不會增加防禦深度;相反,它會產生兩個單點故障。

手冊頁不是說使用 /dev/random 嘛?

這個稍後詳述,保留你的意見。你應該忽略掉手冊頁。不要使用 /dev/random/dev/random 和 /dev/urandom 之間的區別是 Unix 設計缺陷。手冊頁不想承認這一點,因此它產生了一個並不存在的安全顧慮。把 random(4) 中的密碼學上的建議當作傳說,繼續你的生活吧。

但是如果我需要的是真隨機值,而非偽隨機值呢?

urandom 和 /dev/random 提供的是同一型別的隨機。與流行的觀念相反,/dev/random 不提供“真正的隨機”。從密碼學上來說,你通常不需要“真正的隨機”。

urandom 和 /dev/random 都基於一個簡單的想法。它們的設計與流密碼的設計密切相關:一個小秘密被延伸到不可預測值的不確定流中。 這裡的秘密是“熵”,而流是“輸出”。

只在 Linux 上 /dev/random 和 urandom 仍然有意義上的不同。Linux 內核的 CSPRNG 定期進行金鑰更新(透過收集更多的熵)。但是 /dev/random 也試圖跟蹤核心池中剩餘的熵,並且如果它沒有足夠的剩餘熵時,偶爾也會罷工。這種設計和我所說的一樣蠢;這與基於“金鑰流”中剩下多少“金鑰”的 AES-CTR 設計類似。

如果你使用 /dev/random 而非 urandom,那麼當 Linux 對自己的 RNG(隨機數生成器)如何工作感到困惑時,你的程式將不可預測地(或者如果你是攻擊者,非常可預測地)掛起。使用 /dev/random 會使你的程式不太穩定,但這不會讓你在密碼學上更安全。

這是個缺陷,對嗎?

不是,但存在一個你可能想要瞭解的 Linux 核心 bug,即使這並不能改變你應該使用哪一個 RNG。

在 Linux 上,如果你的軟體在引導時立即執行,或者這個作業系統你剛剛安裝好,那麼你的程式碼可能會與 RNG 發生競爭。這很糟糕,因為如果你贏了競爭,那麼你可能會在一段時間內從 urandom 獲得可預測的輸出。這是 Linux 中的一個 bug,如果你正在為 Linux 嵌入式裝置構建平臺級程式碼,那你需要瞭解它。

在 Linux 上,這確實是 urandom(而不是 /dev/random)的問題。這也是 Linux 核心中的錯誤[9]。 但它也容易在使用者空間中修複:在引導時,明確地為 urandom 提供種子。長期以來,大多數 Linux 發行版都是這麼做的。但不要切換到不同的 CSPRNG。

在其它作業系統上呢?

FreeBSD 和 OS X 消除了 urandom 和 /dev/random 之間的區別;這兩個裝置的行為是相同的。不幸的是,手冊頁在解釋為什麼這樣做上乾的很糟糕,並延續了 Linux 上 urandom 可怕的神話。

無論你使用 /dev/random 還是 urandom,FreeBSD 的核心加密 RNG 都不會停擺。 除非它沒有被提供種子,在這種情況下,這兩者都會停擺。與 Linux 不同,這種行為是有道理的。Linux 應該採用它。但是,如果你是一名應用程式開發人員,這對你幾乎沒有什麼影響:Linux、FreeBSD、iOS,無論什麼:使用 urandom 吧。

太長了,懶得看

直接使用 urandom 吧。

結語

ruby-trunk Feature #9569[10]

現在,在嘗試檢測 /dev/urandom 之前,SecureRandom.random_bytes 會嘗試檢測要使用的 OpenSSL。 我認為這應該反過來。在這兩種情況下,你只需要將隨機位元組進行解壓,所以 SecureRandom 可以跳過中間人(和第二個故障點),如果可用的話可以直接與 /dev/urandom 進行互動。

總結:

/dev/urandom 不適合用來直接生成會話金鑰和頻繁生成其他應用程式級隨機資料。

GNU/Linux 上的 random(4) 手冊所述……

感謝 Matthew Green、 Nate Lawson、 Sean Devlin、 Coda Hale 和 Alex Balducci 閱讀了本文草稿。公正警告:Matthew 只是大多同意我的觀點。


via: https://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/

作者:Thomas & Erin Ptacek[12] 譯者:kimii 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

贊(0)

分享創造快樂