Date

关于 /dev/urandom

Myths about /dev/urandom

If you are unsure about whether you should use /dev/random or /dev/urandom, then probably you want to use the latter. As a general rule, /dev/urandom should be used for everything except long-lived GPG/SSL/SSH keys.

引用自 man 4 unrandom

True randomness

在作者看来真正的随机来源于量子效应,但是真实世界中并不需要这种完美的随机数。因为几乎所有我们使用的加密算法都不符合信息理论安全性(information-theoretic security),他们仅能提供提供计算安全性(computational security)。这两者的不同之处在于信息理论安全算法就算攻击者具有无限的计算能力也无法破解。现在之所以使用诸如 AES,RSA 这些仅保证计算安全的算法是因为他们在一定时间内是无法进行被暴力破解的。换句话说,即使你获得了真正的随机数将他们用于这些加密算法中也只能保证计算安全性。实际中,只要无法预测下一个数字,便可认为是随机的

Structure of Linux's random number generator

一般认知:

structure-wrong

来源于外部的随机值被收集,计算熵(entropy)后一方面经过 de-biasing 和 whitening 处理,添加到内核的熵池(entropy pool)中,另一方面会加到内部的熵计数中。对于 /dev/random 来说,如果熵计数(entropy count)大于所请求的数字(判断是否积攒了足够的随机性),则会从池中取出随机数,并减少熵计数;否则会阻塞直至满足条件。所以说 /dev/random 产生的随机数就是来源于外界的那些,只是多了一些预处理。/dev/urandom 也会做同样的事情,只是它在当前的熵计数不满足要求时不会阻塞,而是会通过 CSPRNG(cryptographically secure pseudorandom number generator,密码学安全的伪随机数生成器) 来获取"低质量"的随机数

在这种模式下,由于 CSPRNG 只会在首次从池中拿随机数作为中种子(seed),避免 /dev/urandom 是合乎情理的

真实情况:

structure-real

第一个区别是 CSPRNG 并不作为在熵计数不足时的替代策略,而是整个过程中不可缺少的一部分。每个来源于外部的随机数都会经过 CSPRNG 处理,然后放到随机数池中。第二个区别是熵值是估计的,Linux 内核通过事件的到达时间来估计熵。/dev/random 会从池中获取随机数,而 /dev/urandom 则通过 CSPRNG 获取,但它们的直接来源是相同的。外界不断输入的熵能提供更多的随机性,它会重置随机数生成器的种子值(seed)。因为对于 CSPRNG 来说,固定的种子值所产生的随机数是可以预测的

与 FreeBSD 不同,Linux 上的 /dev/urandom 不会发生阻塞,安全性取决与一些初始的随机种子。在 Kernel 有机会收集熵之前,Linux 的 /dev/urandom 会返回一些不是那么随机的数字,比如系统启动时。而 FreeBSD 则不同,它没有 /dev/random/dev/urandom 的区别,二者是同一个设备。首次调用 /dev/random 会阻塞直至收集到足够多的熵,之后便再也不会阻塞。Linux 3.17 后,Linux 添加了一个新的系统调用 getrandom(2)。它源自于 OpenBSD 的 getentropy(2)。这个系统调用会阻塞直至收集到足够的熵,然后便不会再发生阻塞。一些 Linux 的发行版会在系统关闭时保存一些随机数,以便下次启动时使用