`/dev/urandom`是否适用于模拟目的?

3
似乎在类unix系统中,使用纯C语言从/dev/urandom读取数据是提取高质量随机字节最简单的方法。我需要运行一个模拟程序,每秒大约需要10k个32位随机数,它可能会运行几天。使用/dev/urandom是否适合这个目的?当熵池耗尽时,这里的随机字节的质量如何?
编辑1:
虽然我现在在我的笔记本电脑上为/dev/urandom运行了3个并行的diehard测试,但我得到了以下有趣的行。测试还没有完成。
#=============================================================================#
        test_name   |ntup| tsamples |psamples|  p-value |Assessment
#=============================================================================#
 diehard_parking_lot|   0|     12000|     100|0.99573896|   WEAK
        diehard_sums|   0|       100|     100|0.00116464|   WEAK
          sts_serial|   7|    100000|     100|0.99996076|   WEAK

3
请勿因个人不喜欢某个问题而毫无解释地进行负评。 - user3810155
4
请具体说明您的问题。您需要哪种分布?您需要重复序列吗?您需要加密安全性的随机数吗?对于您的应用程序,/dev/urandom 可能是可以使用的(它是一个CSPRNG),除非您需要重复序列。 - Michael Foukarakis
@MichaelFoukarakis 我现在使用Linux,但如果其他系统有一些问题,了解这一点也是很好的。它不需要具有加密安全性,但我不希望在4294967296个周期后出现相同的随机序列。 - user3810155
@MichaelFoukarakis 我提出这个问题是因为在谷歌上很难搜索到/dev/urandom使用的底层算法,或者当熵池耗尽时会发生什么。换句话说,情况有多糟糕? - user3810155
3
@xiver77提到有许多周期远超过2^32次迭代的伪随机数生成器(PRNGs)。例如,Mersenne Twister的周期为2^19937-1。我建议使用PCG,并从/dev/urandom中提取一个初始状态作为种子。 - r3mainer
显示剩余11条评论
4个回答

3
/dev/urandom的底层实现中,存在一个CSPRNG,其输出池具有最大周期小于2^(26∗32) − 1,然后将其输入SHA-1以产生/dev/urandom的输出。因此,urandom显然可以产生所需数量的随机数,但它无法提供可重复的结果 - 您必须自己缓存您得到的序列。
您不必担心熵池的估计如何耗尽,/dev/urandom将为您输出您要求的任何内容。 urandom(4)手册所说的“理论攻击”是不存在的。(该“问题”是对“熵估计”误解的巨大误解) 许多具有可重复播种的大周期PRNG存在,例如C++中的Mersenne Twister,xorshift PRNG等。您应该能够将任何PRNG适应于适合您目的的分布。

2
关于熵池耗尽时从 [/dev/urandom] 产生的随机字节的质量,奥尼尔(2014)指出,用于加密目的的生成器的设计者与通用随机数生成器相比,“对统计特性(如均匀性)没有同样的关注”。
这可能解释了为什么 /dev/urandom 的输出即使在耗尽后也被认为是好的,但其输出仍无法通过统计测试。
如果您想将 /dev/urandom 和用于模拟目的的标准生成器(如 Mersenne Twister)的属性结合起来,我的建议是将两个数据流进行异或运算。这两种方法足够不同,不应互相抵消。
参考文献:http://www.pcg-random.org/paper.html

值得注意的是,如果存在硬件随机数生成器,Linux内核会将字节合并到/dev/urandom输出(和池)中。较新的英特尔CPU有一个这样的功能。因此测试结果可能会受到测试机器的影响。 - Joachim Wagner

1
不,/dev/random和/dev/urandom是为密码学应用程序设计的,在这些应用程序中,您希望以速度为代价获得非常高的熵。与良好的非CS PRNG相比,它们运行非常缓慢,因此无法为模拟或蒙特卡罗积分提供足够的样本。
对于这些情况,请使用快速但质量良好的PRNG,如XOR-shift+或Mersenne Twister。如果您不需要可重复性,则可以使用/dev/urandom中的数据来初始化PRNG。

速度不是问题。问题要求40 KB/s。在我2013年的笔记本电脑上,urandom输出4 MB/s。 - Joachim Wagner

0

不,你不应该过度使用/dev/urandom,至少根据文档是这样的[尽管如果你读评论线程,你会发现有人认为文档是误导性的]:

内核随机数生成器旨在产生少量高质量的种子材料来种植加密伪随机数生成器(CPRNG)。它专为安全而设计,而不是速度,并且不适合生成大量随机数据。用户在从/dev/urandom(和/dev/random)读取种子材料的数量上应非常节俭;不必要地从此设备读取大量数据将对设备的其他用户产生负面影响。(来源:linux man 4 random)

早期(2.6之前)的Linux实现中,/dev/urandom共享熵池,用于/dev/random/dev/urandom,但现在使用的熵池有些是独立的,从/dev/urandom读取不会影响/dev/random的可用性。其他操作系统使用不同的策略。例如,在FreeBSD中,只有一个随机设备,在系统启动时才会阻塞。

总的来说,我的建议是将熵视为一种资源,在没有明确需要的情况下不要消耗大量熵,这样可以避免过于频繁和不必要的系统调用,这些调用相对较昂贵。

无论如何,在蒙特卡罗模拟中,如果不需要加密随机性,则可以使用良好的伪随机数生成器;对于独立试验,应该从单个/dev/urandom读取中种子PRNG。(从time(NULL)进行种子初始化永远不是一个好主意。)


1
“这是一个虚假的说法,请不要误导人们。没有这样的问题。在urandom被种子化之后,任何应用程序都可以读取这些设备,而无需担心其他任何事情。” - Michael Foukarakis
1
@MichaelFoukarakis 为rici辩护,这个误解在官方文档中存在。而且它并不完全是一个误解,它也是防止所有加密算法完全崩溃的一种防御措施。但这仍然不是使用/dev/random来生成任何东西,包括加密密钥的理由。 - Gilles 'SO- stop being evil'
1
@MichaelFoukarakis:如果您确信Linux manpage是错误的,那么您应该提交文档补丁。这无疑会比这个问题的97个读者更多地到达人们,他们不一定会一直阅读这个答案的评论,并且可能会超过您演讲的观众。我读了djb的文章,对我来说,它似乎站在使用单个良好随机化种子和确定性(但加密安全)的进程内RNG的一边。Thomas Hühn的文章(http://www.2uo.de/myths-about-urandom/)对我来说更具信息价值,供参考。 - rici
@MichaelFoukarakis:提交Linux man页补丁的方法:https://www.kernel.org/doc/man-pages/patches.html - rici
@michael,请提供链接。以及被拒绝的建议补丁。 - rici
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接