用於生成隨機數的 ANSI X9.31 標準
NIST 推薦的基於 ANSI X9.31 附錄 A.2.4 使用 3 鍵三重 DES 和 AES 算法的隨機數生成器對於所需的每個 64 位隨機數據塊使用 3 次 3DES,例如
$ I = ede_K (DT) $ ,並且新由生成。 $ R = ede_K(I \oplus V) $ $ V $ $ V = ede_K(R \oplus I) $
OpenSSL 似乎在ECB 模式下使用3DES ( fips_rand.c )。
我的問題是……如果您有一個在 CTR 模式下執行的密碼,您是否可以根據需要加密一串空字節,而不是對每個塊進行三個不同的加密輪次?
另外,DT 的推薦格式是什麼?通常時間戳是 32 位,而不是 64 位。
如果你問為什麼 X9.31 rng 是這樣設計的,而不是其他方式,我不確定除了原作者之外是否有人可以說。核心設計至少可以追溯到 1985 年(它包含在 X9.17 中),最初使用的是 DES(後來升級為使用 3DES)。我懷疑原作者對在計數器模式下使用 DES 沒有信心。
至於 DT 格式,X9.31 中的要求是每次生成塊時值都是不同的。它的存在是為了確保 RNG 不會陷入短週期,因此如果 DT 只是偶爾更改也不會很糟糕(例如,如果您使用相同的 DT 生成 256 個值,那麼密碼遇到的機率這 256 個值的周期約為 $ 2^{-56} $ )。第二個原因是向 RNG 提供少量額外的熵——儘管它並沒有那麼好。只要您遵守這一點,任何格式都可以。就您而言,遵守法律的精神和文字很容易;制定一個 DT,其中前 32 位是您從系統獲得的時間戳,而低 32 位只是一個計數器,每次生成塊時都會遞增。這樣,DT 值每次都會改變(因為低 32 位總是改變),並且你從目前數據/時間中提供少量的熵。
至於 OpenSSL,它似乎是 X9.31 的實現(使用 2-key 3DES;這是 X9.31 最初要求的,但是您現在提供的 NIST 文件指定了 3-key 3DES)。
此外,如果您需要一個安全的 RNG,我建議您查看這些 RNG,尤其是 CTR_DRBG(其基本思想只是計數器模式下的分組密碼,就像您建議的那樣)。