在 Linux 上,/dev/random 解除阻塞是否意味著 /dev/urandom 已播種?
Linux 有一個熟悉的問題,即 /dev/random 阻塞太多(堅持在資訊理論上是安全的),而 /dev/urandom 沒有足夠阻塞(它會在數據被充分播種之前返回數據)。新的
getrandom()
系統呼叫做了正確的事,但在撰寫本文時,它還沒有在主要發行版中普遍可用。我的問題是:如果我成功地從 /dev/random 讀取了一個字節,這是否意味著 /dev/urandom 已播種?我花了一些時間盯著http://lxr.free-electrons.com/source/drivers/char/random.c但一直沒能弄明白。設備驅動程序提供的熵混合到輸入池中,然後輸入池提供單獨的
/dev/random
和/dev/urandom
輸出池,但我無法收集觸發從輸入池傳輸到輸出池的條件,或者(因此)是否可能/dev/random 在 /dev/urandom 餓死時被餵食。
我終於解開了這段程式碼在做什麼。
是的。
為什麼這是正確的快速版本是系統收集的前 128 位熵直接混合到非阻塞池中,繞過輸入池。實現這一點的邏輯是每個
add_foo_randomness()
功能的一部分:r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool;
http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L804
http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L924
並且根據http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L677,
nonblocking_pool.initialized
在entropy_total
超過 128 位時設置。因此,當 /dev/random 提供任何內容時,/dev/urandom 已被播種。為了完整起見,以下是有關如何管理熵池的其餘部分:
所有池,即使是非阻塞池,都有熵估計,當新熵混合時記入貸方,當熵被提取時記入記賬。
如上所述,收集的前 128 位熵被寫入並記入非阻塞池;此後的所有內容都被寫入並記入輸入池。
如果輸入池溢出(即其熵估計接近其總大小),則這會交替觸發從輸入池到阻塞池或非阻塞池的轉移。如果池已滿 75%,則池跳過輪次。(http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L692)
從 /dev/random 讀取總是會觸發從輸入池到阻塞池的傳輸(http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L1177)。僅當過去 60 秒內沒有此類傳輸時,從 /dev/urandom 讀取才會觸發從輸入池到非阻塞池的傳輸(http://lxr.free-electrons.com/source/drivers/char/random .c?v=4.5#L983)。
轉移的金額是(http://lxr.free-electrons.com/source/drivers/char/random.c?v=4.5#L995):
- 通常等於從 /dev/{u}random 讀取的數量
- 但至少 64 位
- 但不超過輸入池的目前熵估計
- 如果傳輸到非阻塞池,則不超過該估計值 - 128 位。(編輯:我認為這是一個錯誤。見http://marc.info/?l=linux-kernel&m=145945873501946&w=2)