虚拟机具有虚拟硬件,但这并不一定意味着它们完全没有熵源。特别是中断:虽然 VM 没有真正的中断生成器硬件,但它的操作系统仍然接收此类“中断”作为硬件仿真的一部分。例如,当您通过 SSH 连接到您的虚拟机时,网络数据包仍然来回流动,并且每个传入数据包都会触发虚拟机中的模拟中断。内核从此类中断中得出的熵来自该中断出现的确切时间,在这种情况下,它是数据包实际到达主机系统物理网络接口的函数。从传入数据包到中断的过程比在非虚拟机中更复杂,因为主机和 VM 层介于两者之间,
VM 和随机性的一个更紧迫的问题是VM 克隆。您可能想要安装和配置一个完整的虚拟机,然后制作快照并克隆它,以便轻松创建几个新的已配置虚拟机。不幸的是,这意味着所有克隆都从完全相同的内部 RNG 状态开始。一旦启动,它们就会开始发散,因为每个都积累了自己的“随机事件”(即使硬件是模拟的,模拟的硬件事件仍然间接来自真正的硬件随机事件,如上所述)。计算方面的分歧可能很慢(可能需要几秒钟,对于每秒可以执行数十亿次操作的计算机来说,这非常长)。
解决这个问题的最完整方法是通过使用从其他地方的其他随机源获得的种子为每个 VM 播种来强制随机性;这就像将一些文件写入/dev/random. 如果您克隆 VM,这可能是可取的;否则,这可能是无用的(但无论如何它不会有害)。请注意,每个 VM 只需要这样做一次:正常的 Linux 发行版将在关机时生成并保存一个“种子文件”,并在下次启动时重用它,因此一旦为 VM 播种,它就会保持播种。
至于您的 #2 解决方案,请注意/dev/random和/dev/urandom(在 Linux 中)之间的区别并不完全是您所说的。/dev/random如果它估计其内部池没有足够的熵,将阻塞;但它也认为其池在使用时已耗尽。在收集到足够的熵之前阻塞是可以的;但是“耗尽效应”意味着更多的阻塞,而且只有非常脆弱的科学依据。这是 Linux 的一个已知缺陷/dev/random。/dev/random使用 FreeBSD (以及扩展为 Mac OS X)会得到一个更理智的行为:它会阻塞直到收集到足够的初始熵,然后它会使用加密安全的 PRNG 生成任意数量的字节,而无需阻塞。请注意,FreeBSD/dev/random并且/dev/urandom完全相同(这很好)。
无论如何,即使是 Linux/dev/random在熵耗尽方面的疯狂行为也会被虚拟机克隆所愚弄。因此,坚持生成密钥/dev/random不仅会让您等待过多的时间;在存在 VM 克隆的情况下,它也可能无法实际达到所需的随机性水平。
总而言之,您的#3 解决方案是正确的。