用於生成 openssl 密鑰的良好熵源
我需要為 openvpn 生成 CA(4096 位 RSA)和伺服器密鑰,我希望它們是“頂級質量”。這是我的計劃:
- 從多個來源收集熵(保存單個文件):FreeBSD Yarrow、Linux(在 entropy_avail 為 4096 時使用 haveged 守護程序)、ANU QRNG、其他東西(例如,使用隨機密碼加密的 wifi 擷取文件,其他建議)
- 將所有隨機文件混合成一個文件
- 使用結果播種 openssl -rand$$ myrndfile $$生成密鑰時
如果我的計劃聽起來不錯:
- 隨機文件的大小應該是多少?
- 將文件混合成一個文件的最佳方法是什麼?
首先,使用“-rand”只是播種 OpenSSL RNG。它可以是 1 字節或 1 TB。它僅用作在內部開始工作的種子。然後,OpenSSL 將使用系統熵來實際生成 RSA 所需的素數。
此外,熵只是序列中不可預測性的度量,而不是實際的儲存位池。對熵的估計越大,某些事物就越有可能具有不可預測的行為,例如隨機數序列。
儘管如此,Linux 核心文件 /proc/sys/kernel/random/entropy_avail 只是一個估計值。當您擁有“4096 位”的熵池時,這僅意味著生成的隨機數具有您可以產生的最高質量的不可預測性。隨著熵池估計的下降,隨機數序列的可信度也會下降。當熵池為 0 時,核心將阻塞生成隨機數據,直到池可以再次被填滿。當您生成隨機數據時,它會減少對熵的估計。這是 /dev/random 的行為。
換句話說,把熵池想像成一個“密碼溫度計”。當儀表處於“滿”狀態時,生成的數字將非常困難,即使不是幾乎不可能重現,並且高度不可預測。當儀表完全為空時,生成隨機位可以由對系統知之甚少的第三方准確地複制。
因此,請回答您的 OpenSSL 密鑰問題。OpenSSL 將希望核心盡可能地保持熵。但是,預設情況下,OpenSSL 將從 /dev/urandom 播種。該設備仍會耗盡熵,但不會在沒有熵估計時阻塞,而是使用 PRNG 生成其餘數據。保持熵池充滿,PRNG 將永遠不會被使用。
FreeBSD 上的 /dev/random 設備是嚴格的 PRNG,而不是 TRNG。正如您所提到的,它使用 Yarow 算法來生成隨機數。然而,在生成 2^256 個數字後,循環重複,以與之前完全相同的順序生成完全相同的數字,就像所有 PRNG 的情況一樣。相比之下,Linux核心中的/dev/urandom使用的是SHA1,在熵池耗盡的情況下,會在回收前總共生成2^160個數字。
現在,來解決你的問題。您提到您在 Linux 中使用 haveged(8) 來保持熵儲備滿。在大多數係統上,haveged(8) 為核心生成大約 1 MBps 的真實隨機數據,並使用 ioctl() 系統呼叫來增加熵計數器。因此,生成 4096 位 RSA OpenSSL 密鑰將具有您可能要求的最高質量的加密強度,並且從其他系統添加額外的隨機數據不會增加其強度。
證書生成的重點是從您的文件或隨機數生成器創建隨機數,作為生成非常大素數的算法的雜訊輸入。訣竅是得到那些素數。由於有一個 4096 位的熵池,並且始終充滿,正如 haveged(8) 將提供的那樣,即使某人完全了解您的系統,他們重新生成相同素數的能力也是極不可能的。
因此,在我看來,執行 haveged(8) 將核心保持在 4096 位的熵之上,並使用“-rand /dev/random”在那裡生成您的證書,而不是從每個系統生成一個文件。
OpenSSL Wiki 和原始碼都指向隨機種子函式,僅使用提供的前 32 個字節(256 位)來為加密強 PRNG 提供種子。任何額外的字節都會被丟棄。話雖這麼說,好的做法是用完整的 32 個字節播種,並使它們盡可能“隨機”。此外,該函式應該被強制重新播種或再次呼叫新的種子,為每個新密鑰或生成的隨機數提供一個新種子,以確保來自 CS-PRNG 的同一流不會用於多個密鑰。如果你有很多你認為是隨機的數據並且真的覺得你必須合併所有的數據,那麼使用散列函式來生成 32 字節的種子(但是,那麼你相信散列函式沒有弱點(但是這個可能是較小的擔憂之一)。總結: