在 linux 中 /dev/random 基于“环境变量”,而 /dev/urandom 基于算法和时间。我的问题是:
/dev/random 从哪里收集这些变量。
如果您将两台机器设置为相同的时间(精确到毫秒 - 如果可能)并且具有相同的速度、操作系统等...并且对 /dev/urandom 进行 X 字节数的十六进制转储,它们是否会具有相同的精确值(因为时间相同)?
答案1
/dev/urandom 从哪里收集这些变量。
它可以在所有地方发挥作用,主要是中断计时。例如,如果您有网卡,数据包到达的精确时间将受到网卡上的晶体时基与为 CPU 计时的晶体时基之间的偏移的影响。两个石英晶体振荡器之间的偏移受到微观区域温度变化的影响,这些变化被认为是真正物理随机的。
如果您有一个旋转磁盘,则读取完成的时间取决于磁盘旋转的速度。这受到磁盘表面和磁盘组件内部空气之间的湍流剪切力的影响。虽然这不被认为是真正的物理随机性,但它是任何已知机制完全无法预测或重复的。
如果您将两台机器设置为相同的时间(精确到毫秒 - 如果可能)并且具有相同的速度、操作系统等...并且对 /dev/random 进行 X 字节数的十六进制转储,它们是否会具有相同的精确值(因为时间相同)?
嗯,毫秒还远远不够。你需要与 CPU 测量时间处于同一水平——十亿分之一秒。但当然,必须如此。否则,如果你看到一台机器的状态,你就能 100% 确定另一台机器不可能有相同的状态。而且由于状态应该是随机的,你不应该能够通过查看任何其他机器并 100% 确定地了解该状态。只要实现这一目标的几率足够低(比如,小于 2^100 分之一),那么就完全没问题。
即使你掷两个骰子,每个骰子都有十亿面,它们的结果也可能相同。只要它们每十亿次只有一次结果相同,那就理所当然。
答案2
看一下urandom
的手册,特别是描述:
读取时,/dev/random 设备将仅返回熵池中估计的噪声位数内的随机字节。/dev/random 应该适合需要极高质量随机性的用途,例如一次性密码本或密钥生成。当熵池为空时,/dev/random 的读取将被阻止,直到收集到额外的环境噪声。
从 /dev/urandom 设备读取不会因等待更多熵而阻塞。因此,如果熵池中没有足够的熵,则返回的值在理论上容易受到驱动程序使用的算法的加密攻击。目前未分类的文献中没有关于如何做到这一点的知识,但理论上可能存在这样的攻击。如果您的应用程序担心这一点,请改用 /dev/random。
不幸的是,我无法真正回答你的第二个问题,我使用别人可以,但我的猜测是非常很难在两台机器上获得完全相同的结果。
答案3
在 linux 中 /dev/urandom 基于“环境变量”,而 /dev/random 基于算法和时间。
这两个假设都是错误的。
根据随机(4) - Linux 手册页1、/dev/random
将来自设备驱动程序和其他来源的环境噪声收集到熵池中。
鼠标就是此类设备的一个例子。2尝试执行
head -c 1024 /dev/random | base64
清除熵池(几秒后中止),然后
head -c 40 /dev/random | base64
从 读取 40 个字节/dev/random
。不执行任何操作,观察是否head
停止对数时间,因为池中没有新的熵。
中止,然后执行
head -c 40 /dev/random | base64
再次。这一次,快速地从左到右移动鼠标。head
将快速完成其任务。
再次,根据随机(4) - Linux 手册页,/dev/urandom
使用相同的熵池,但不会阻塞。如果熵池不够大,它会回退到伪随机数生成器(PRNG)创建更多(伪)随机输出。
1实际行为可能因发行版不同而有所差异。
2示例适用于 Ubuntu 12.04。其他发行版可能有所不同。