如果使用安全種子,如何利用 C rand()?
我剛剛開始做一個關於 CSPRNG 的研究項目,我想知道正常 PRNG 的安全種子有哪些漏洞。例如,如果我使用 LavaRnd 生成一個隨機數來播種 srand(),然後使用 rand() 生成一些大密鑰,攻擊者可以做些什麼來解析該密鑰,或者找到關鍵資訊?
我看到很多人有類似的問題,但答案通常歸結為“結果不會有足夠的隨機性”,然後對細節有很多揮手致意。但這對現實世界的實施意味著什麼?使用安全種子可以在不安全的偽隨機數生成器上安裝哪些實際漏洞或攻擊?
ISO/IEC 9899:1990 版本的 C 標準包含:
範例 以下函式定義了
rand
和的可移植實現srand
。static unsigned long int next = 1; int rand(void) // RAND_MAX assumed to be 32767 { next = next * 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } void srand(unsigned int seed) { next = seed; }
這個生成器的狀態完全由變數的 31 個低位來表徵
next
。如果我們在問題中*“使用 LavaRnd 生成一個隨機數作為種子,然後使用* ”srand()
生成一些大密鑰 ,那麼只有rand()
$ 2^{31}=2147483648 $ *“大密鑰”*的結果(最多)是可能的,完全由 input 的 31 個低位決定seed
。然後允許嘗試所有這些密鑰的攻擊。如果測試密鑰需要 $ 2^{20} $ 一個時鐘週期(約一百萬) $ 2^3 $ - 核心 CPU 執行在 $ 2^{31} $ Hz,攻擊預計會持續 $ 2^{31+20-3-31-1}=2^{16}=65536 $ 秒,也就是不到一天。
*根據對“大鑰匙”*所做的事情,可能會有更快的攻擊。例如,如果
rand()
還用於生成初始化向量(通常位於加密消息的開頭),就會出現這種情況。一個簡單的攻擊可以next
從 的三個連續值中找到 的值rand()
。從字面上看,這只需不到一眨眼的時間,就可以毫不費力地找到所有過去和未來的輸出,rand()
而不會被srand()
.另一方面,也許上述 $ 2^{20} $ 週期估計太低(可能是 RSA 密鑰的情況)。但無論如何,31 位的密鑰空間都太低了。目前,實際安全性的門檻值接近 80 位,取捨 20。128 被認為可以在 2030 年之前使用,除非有人相信仙女或量子電腦很快就會用於密碼分析。