操作系统如何为随机种子创建熵?


19

在Linux上,文件/dev/random/dev/urandom文件分别是伪随机字节的阻塞和非阻塞源。

它们可以作为普通文件读取:

$ hexdump /dev/random
0000000 28eb d9e7 44bb 1ac9 d06f b943 f904 8ffa
0000010 5652 1f08 ccb8 9ee2 d85c 7c6b ddb2 bcbe
0000020 f841 bd90 9e7c 5be2 eecc e395 5971 ab7f
0000030 864f d402 74dd 1aa8 925d 8a80 de75 a0e3
0000040 cb64 4422 02f7 0c50 6174 f725 0653 2444
...

许多其他UNIX变体提供/dev/random/dev/urandom为好,不阻塞/非阻塞的区别。

Windows的等效CryptGenRandom()功能是

操作系统如何生成伪随机性?


你做了什么研究?您是否看过标准网站,例如Wikipedia或Security.SE或Crypto.SE?维基百科对此有一篇文章:en.wikipedia.org/wiki//dev/random。当Wikipedia上有一篇文章回答您的问题时,这就是没有进行足够研究的定义。(我们希望您在问这里之前先做大量研究,然后向我们展示您已完成的问题研究。)
DW

Answers:


31

问题的标题和正文提出两个不同的问题:操作系统如何创建熵(这实际上应该是获取熵),以及操作系统如何从该熵产生伪随机性。我将从解释差异开始。

随机性来自何处?

随机数生成器(RNG)有两种类型:

  • 伪随机数生成器(PRNG),也称为确定性随机位生成器(DRBG)或它们的组合,是确定性算法,可维护固定大小的可变内部状态并从该状态计算其输出。
  • 硬件随机数生成器(HRNG),也称为“真”随机数生成器,是基于物理现象的。“真实”有点用词不当,因为没有已知真正随机的信息源,只有未知的可预测信息源。

某些应用程序(例如物理现象的模拟)可能会满足通过统计测试的随机数。其他应用程序(例如生成加密密钥)需要更强的属性:不可预测性。不可预测性是安全属性,不是(仅)统计属性:这意味着对手无法猜测随机数生成器的输出。(更准确地说,您可以通过测量对手猜测RNG输出的每一位的概率来衡量RNG的质量。如果该概率与1/2明显不同,则表明RNG不好。)

有些物理现象会产生具有良好统计特性的随机数据,例如,放射性衰变,对背景噪声的某些天文观测或股市波动。这样的物理测量需要调节白化),以将偏差的概率分布转换为均匀的概率分布。大家都知道的物理测量方法并不适合密码学:股市波动可能对地理哈希有用,但是您不能使用它们来生成密钥

密码学需要保密:对手必须不能发现进行调节的数据。存在密码安全的伪随机数生成器(CSPRNG):PRNG算法,其输出除了具有良好的统计特性外,还适合用于密码应用。使CSPRNG 加密安全的特性之一是,它的输出不允许对手重建内部状态(知道所有位,但CSPRNG产生的一位无助于找到丢失的位)。我不会介绍CSPRNG的制作方法,因为这很简单-您可以遵循专业密码学家提供的食谱(使用标准算法,例如NIST SP 800-90A中的 Hash_DRBG,HMAC_DRBG或CTR_DRBG)或ANSI X9.31 PRNG。为了确保安全,CSPRNG需要其状态的两个属性:

  • 必须从头开始并始终将状态保密(尽管暴露状态不会透露过去的输出)。
  • 状态必须是线性的:RNG绝不能从同一状态开始两次。

随机数生成器的体系结构

实际上,几乎所有好的随机数发生器都将CSPRNG与一个或多个熵源结合在一起。简而言之,熵是对数据源不可预测性的一种度量。仅基于硬件RNG的随机数生成器很难:

  • 无论如何,原始物理数据可能都需要进行条件处理,以将概率数据转换为统一的分布。
  • 随机源的输出必须保密。
  • 与需求相比,熵源通常很慢。

因此,操作系统中的RNG 几乎总是这样工作

  1. 积累足够的熵以建立不可预测的内部状态。
  2. 使用累积的熵作为种子,即作为内部状态的初始值,运行CSPRNG
  3. 可选地,定期将其他熵混合到内部状态中。(这不是严格必要的,因为熵不会以任何可测量的速率“消耗”。它有助于防止泄漏RNG状态的某些威胁而不会损害整个系统。)

随机数生成服务是操作系统工作的一部分,因为熵收集需要访问硬件,并且熵源构成了共享资源:操作系统必须组装它们并从中获取适合应用的输出。在操作系统中需要对熵源进行伪随机调节。它也可能是加密安全的,因为从根本上讲这并不困难(并且在应用程序彼此不信任的操作系统上是必需的;在完全协作的系统上,如果操作系统需要运行,则每个应用程序必须在内部运行自己的CSPRNG仍然没有提供)。

大多数具有持久性存储的系统在启动时都会从磁盘加载RNG种子(我将使用“ disk”作为任何一种持久性存储的缩写),并使用从该种子生成的一些新的伪随机数据覆盖种子,或与从该种子生成的随机数据以及其他熵源一起提供(如果可用)。这样,即使重新启动后熵不可用,来自前一个会话的熵也会被重用。

必须注意保存状态。还记得我说过的状态必须是线性的吗?如果从相同的磁盘状态启动两次,您将获得相同的RNG输出。如果您的环境中有这种可能,则需要另一个熵源。从备份还原或克隆虚拟机时,请当心。一种克隆技术是将存储的熵与一些可预测但唯一的环境数据(例如时间和MAC地址)混合;请注意,如果环境数据是可预测的,则拥有存储的VM状态的任何人都可以重建派生的VM实例的种子。

熵源

查找(并正确使用)熵源是操作系统中随机数生成过程中最具挑战性的部分。可用的熵源将必然取决于硬件以及硬件在哪个环境中运行。

如果幸运的话,您的硬件将提供一个可用作熵源的外围设备:专用或旁侧的硬件随机数生成器。例如:

NIST SP800-90B提供了硬件RNG的设计指南。评估硬件RNG 很难。硬件RNG通常是精致的野兽,需要小心使用:许多类型的RNG在启动后需要一些时间,在两次读取之间需要一些时间才能使其不稳定,它们通常对环境条件(例如温度等)敏感。

基于Ivy Bridge架构的Intel x86-64处理器提供了RdRand说明,该说明提供了CSPRNG的输出,该输出由热噪声引起。大多数智能手机处理器都包含硬件熵源,尽管Android并不总是使用它。

缺乏强熵源的系统必须结合弱熵源并希望(确保一个词太强)足以满足要求。随机移动鼠标在客户端计算机上很流行,并且您可能已经看到某些要求您移动鼠标的加密程序显示安全性(即使在任何21世纪PC操作系统上,操作系统都会积累熵,而应用程序无需打扰)。

如果您想看一个例子,您可以看一下Linux,尽管要注意它并不完美。特别是,/dev/random阻塞过于频繁(因为它阻塞直到可用的熵足够大,对熵的概念过于保守),而/dev/urandom除了第一次启动时几乎总是好的,但是当熵不足时则没有任何指示。Linux具有许多HRNG设备的驱动程序,并累积各种设备(包括输入设备)和磁盘定时的

如果您拥有(机密)持久性存储,则可以使用它来保存一次引导到下一次引导的熵,如上所述。第一次启动是一个微妙的时期:此时系统可能处于相当可预测的状态,尤其是在实质上以相同方式在工厂外运行的批量生产的设备上。在工厂中为某些具有持久性存储的嵌入式设备提供了初始种子(由工厂计算机上运行的RNG产生)。在虚拟服务器环境中,当从主机或从熵服务器实例化虚拟机时,可以设置初始熵。

播种不佳的设备在实践中是一个普遍存在的问题- 对公共RSA密钥研究发现,许多服务器和设备的密钥都是由不良RNG(很可能是良好的PRNG)生成的,而该PRNG种子不足。作为OS设计师,您无法独自解决此问题:控制部署链是实体的工作,以确保RNG在首次启动时能正确植入种子。作为OS设计人员,您的任务是提供一个适当的RNG,包括提供第一个种子的接口,并确保在正确播种RNG之前使用RNG进行正确的错误信号发送。


5
令人震惊的恒星答案。
亚当·玛拉斯

这==太棒了。

我不同意“没有已知的信息来源是真正随机的”。量子力学的普遍(哥本哈根)解释说,测量可能叠加的系统的结果实际上是随机的,因为我们永远无法预测结果,而只能给出概率分布(充其量) 。资料来源:这里的物理研究生
巴尔

3

除了吉尔斯答案外,中断还可以用于建立熵。例如,在Linux中,添加中断处理程序时,您可以定义是否应将此中断的出现用作内核熵池的贡献。

当然,攻击者可能无法确定中断的情况。例如,乍一看,网络流量(即它们产生的中断)似乎是随机性的良好来源。但是,攻击者可能会以某种方式操纵您的流量,从而可以预测您进行某些操作所需的随机性。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.