我应该使用/dev/random
还是/dev/urandom
?
在什么情况下我会更喜欢其中一种而不是另一种?
答案1
长话短说
用于/dev/urandom
大多数实际目的。
较长的答案取决于您所运行的 Unix 的风格。
Linux
历史上,/dev/random
是/dev/urandom
同时推出的。
正如@DavidSchwartz 指出的在评论中,/dev/urandom
在绝大多数情况下首选使用。他和其他人还提供了优秀作品的链接关于的神话/dev/urandom
我推荐进一步阅读的文章。
总之:
- 这联机帮助页具有误导性。
- 两者均由相同的 CSPRNG产生随机性(图2和图3)
/dev/random
当熵耗尽时会阻塞,因此读取/dev/random
可以停止进程执行。- 熵的大小是保守估计的,但没有计算在内
/dev/urandom
永远不会阻塞。- 在极少数情况下,启动后不久,CSPRNG可能没有足够的熵来正确播种,并且
/dev/urandom
可能不会产生高质量的随机性。 - 如果 CSPRNG 最初播种正确,那么熵运行低并不是问题。
- CSPRNG 正在不断地重新播种。
- 在 Linux 4.8 及更高版本中,
/dev/urandom
不会耗尽熵池(由/dev/random
),而是使用上游的 CSPRNG 输出。 - 使用
/dev/urandom
。
规则的例外情况
在密码学堆栈交换中何时在 Linux 中使用/dev/random
over/dev/urandom
@otus给出了两个用例:
在低熵设备上启动后不久,如果尚未生成足够的熵来正确播种
/dev/urandom
。
如果您担心(1),您可以检查可用的熵/dev/random
。
如果你正在做(2),你就会知道了:)
注意:您可以检查从 /dev/random 读取是否会阻塞,但要注意可能的竞争条件。
替代方案:都不使用!
@otus 还指出getrandom()
/dev/urandom
如果初始种子熵不可用,系统将读取并且仅阻塞。
有更改/dev/urandom
用途的问题getrandom()
,但可以想象,/dev/xrandom
基于 来创建新设备getrandom()
。
苹果系统
没关系,因为 维基百科说:
macOS 使用 160 位西洋蓍草基于 SHA1。 /dev/random 和 /dev/urandom 没有区别;两者的行为相同。 Apple 的 iOS 也使用 Yarrow。
自由BSD
没关系,因为维基百科说:
/dev/urandom
只是一个链接/dev/random
,并且只会在正确播种之前阻止。
这意味着在启动后,FreeBSD 足够聪明,可以等到收集到足够的种子熵,然后再提供永无休止的随机优点流。
网络BSD
使用/dev/urandom
,假设您的系统至少已读取一次/dev/random
以确保正确的初始播种。
/dev/urandom
永远不会阻塞。
/dev/random
有时会阻塞。如果已知系统的状态是可预测的,则将在启动时提前阻止。
/dev/urandom
应用程序应该在需要随机生成的数据(例如用于模拟的加密密钥或种子)时读取。系统应设计为在运行任何与互联网通信或需要加密的服务之前从启动时至少明智地读取一次
/dev/random
,以避免可预测地生成密钥。
答案2
这有点像“我也是”的答案,但它强化了汤姆黑尔的推荐。它完全适用于 Linux。
- 使用
/dev/urandom
- 不要使用
/dev/random
根据 Linux Kernel Crypto 邮件列表上的 Theodore Ts'o 的说法,/dev/random
它已经被弃用了十年。从回复:[RFC PATCH v12 3/4] Linux 随机数生成器:
实际上没有人使用/dev/random。它本质上是一个已弃用的接口;十多年来一直推荐的主要接口是 /dev/urandom,现在是 getrandom(2)。
我们定期进行测试/dev/random
,但它经常出现故障。该测试执行三个步骤:(1)/dev/random
通过在非阻塞模式下请求 10K 字节来耗尽; (2) 在阻塞模式下请求 16 字节 (3) 尝试压缩块以查看其是否随机(穷人的测试)。测试需要几分钟才能完成。
这个问题在 Debain 系统(i686、x86_64、ARM 和 MIPS)上非常严重,我们要求 GCC Compile Farmrng-tools
为他们的测试机器安装该软件包。从在 gcc67 和 gcc68 上安装 rng-tools:
我想请求在 gcc67 和 gcc68 上安装 rng-tools。它们是 Debian 系统,当对使用该设备的库进行测试时,/dev/random 在没有 rng-tools 的情况下会遭受熵耗尽。
BSD 和 OS X 显示正常。问题肯定出在Linux上。
还值得一提的是,Linux 不会记录生成器故障。他们不希望这些条目填满系统日志。迄今为止,大多数故障都是无声的,大多数用户都没有发现。
由于内核将打印至少一条失败消息,因此情况很快就会发生变化。从[PATCH] random:沉默编译器警告并修复竞争在内核加密邮件列表上:
具体来说,我添加了
depends on DEBUG_KERNEL
.这意味着这些有用的警告只会刺激其他内核开发人员。这可能正是我们想要的。如果各个相关开发人员看到来自其特定子系统的警告,他们就会更有动力去修复它。分发内核上的普通用户根本不应该看到警告或垃圾邮件,因为通常用户不使用 DEBUG_KERNEL。我认为从安全工程的角度来看,抑制所有消息是一个坏主意。
许多人不运行调试内核。大多数想要或需要了解这些问题的用户不会意识到它的发生。考虑一下,我们了解到 systemd 问题的原因是 dmesg 的问题。
抑制所有配置的所有消息会撒下比必要的更广泛的网。可能被检测到并修复的配置可能会被忽视。如果问题不暴露出来,那么问题就无法解决。
我觉得内核正在为某些组织制定政策决策。对于那些拥有实际上无法修复的硬件的人来说,组织必须根据他们的风险来决定该怎么做。他们可能决定承受风险,也可能决定更新硬件。然而,如果没有有关该问题的信息,他们甚至可能没有意识到他们有一个可操作的项目。
线程后期最终达成的妥协是每个调用模块至少有一个 dmesg。
答案3
/dev/urandom
传统上,和之间的唯一区别/dev/random
是当内核认为系统中没有熵时会发生什么 -/dev/random
关闭失败,/dev/urandom
打开失败。两个驱动程序都从add_disk_randomness()
、add_interrupt_randomness()
和获取熵add_input_randomness()
。/drivers/char/random.c
具体请参见。
编辑添加:从 Linux 4.8 开始,/dev/urandom
已重新设计以使用 CSPRNG。
那么什么时候应该关闭失败呢?适用于任何类型的加密用途,特别是播种 DRBG。有一篇非常好的论文解释了/dev/urandom
在生成 RSA 密钥并且没有足够的熵时使用的后果。读挖掘你的 P 和 Q。