线性同余生成器:设置种子有多重要?

时间:2010-10-07 09:34:58

标签: c++ c random

我在算法和数据结构课程中学习linear congruential generator。在考虑了我们一直在使用的RNG实现(a = 429493445,c = 907633385,mod = 4294967296,X是_uint32)之后,我想到了一件事:程序具有设置种子的功能。

该功能在C和C ++中有多重要?

这是我的想法:一旦程序启动,操作系统会为所有使用的变量分配地址。给予种子的存储器位置中的数据可以被解释为数字。

据我所知,在小型计算机中,可能会发生操作系统(如果有的话)将多次相同的地址分配给种子,但每次包含在该地址中的数据是否会有所不同?除非系统在每次启动后将所有空闲RAM设置为某个值,否则RAM中包含的数据本身将非常随机并提供足够好的种子。

即使给予种子的空间中包含的数据被另一个程序使用,我也看不出它会对发生器本身产生什么影响。

5 个答案:

答案 0 :(得分:2)

虽然对于RNG玩的不愉快,但是在“内存中的垃圾”播种可能会正常工作。但这确实是一种糟糕的做法:你无法保证内存中的数据随机的,即使它可以。在安全应用程序中(我猜这里不相关,因为你使用的是线性同余生成器),你不希望不受你控制的环境部分(RAM)充当种子。在其他应用程序中,例如科学计算,您希望结果具有可重现性。那么你做的通常是让用户为自己选择一个种子,并提供一个选项来为种子的OS RNG(在类UNIX系统上的/ dev / random)进行采样。

最重要的是:如果你想要一个随机种子,那就从一个好的随机来源中获取它。几乎所有操作系统提供的易于访问的源都会比“嘿,今天这个位置的RAM中有什么?”更好。从例如/ dev / urandom进行采样并不比采样RAM困难,并且它是正确的事情(当然,对于非安全敏感的事物)。

编辑:以下是使用C在GNU / Linux上采样/ dev / urandom的方法:

int seed;
FILE* urandom = fopen("/dev/urandom", "r");
fread(&seed, sizeof(int), 1, urandom);
fclose(urandom);

现在seed包含一个可用作PRNG种子的整数(您可能需要不同的数据类型)。

维基百科有some nice information on /dev/random and /dev/urandom

答案 1 :(得分:2)

OpenSSL确实使用未初始化的内存来生成其随机性初始化的一部分。 2年前Debian did remove this发生了一些噪音,认为使用未初始化的变量是一个错误。

请注意,这不是OpenSSL中唯一的熵源

所以是的,未初始化的内存可以用作随机源。但要小心真正了解你在做什么!

答案 2 :(得分:1)

关于PRNG的一个方面是,当您知道它们的参数并设置初始种子时,它们会提供可重现的序列。因此,在这方面,在API中公开这个“功能”是很自然的。许多应用程序需要这种形式的确定性,而真正的RNG设备无法提供它。

编辑:要回答你的实际问题,假设堆栈变量中的数据是随机的是错误的,几乎所有的unix系统都清除堆栈和堆(用0初始化它)作为安全措施,想象你可以读取密码字符串由前一个进程留在内存中。

答案 3 :(得分:1)

随机存储器可用作种子。但是,由于操作系统中的内存分配算法不是随机的,而其他程序生成的数据通常也遵循某种模式,我不认为它是完美的种子。这取决于你的应用程序的目的 - 我肯定不会在银行系统中使用它。 如果你想要更多的随机性,你可以将它作为种子的一部分使用,然后用来自不同来源的其他随机种子来填充它。

答案 4 :(得分:0)

不要将种子设置为 ZERO 。按/dev/urandom初始化将是最佳方式。