伪随机数和真正的随机数有何不同?为何如此重要?


665

我从来没有得到这个。只是说您用任何语言编写了一个小程序,都会掷骰子(仅以骰子为例)。经过60万次滚动,每个数字将被滚动100,000次左右,这是我所期望的。

为什么会有专门针对“真正随机性”的网站?当然,根据上述观察,获得任意数字的机会几乎等于可以选择多少个数字。

我在Python中尝试过:这是6000万次滚动的结果。最高变化约为0.15。这不是随机的吗?

1 - 9997653 2347.0
2 - 9997789 2211.0
3 - 9996853 3147.0
4 - 10006533 -6533.0
5 - 10002774 -2774.0
6 - 9998398 1602.0


21
“掷骰子”是什么意思?它是否装有机械臂和相机?
starblue 2014年

3
尽管我同意您的语气总论,但我们经常对此担心太多,但在现实生活中却被利用:en.wikipedia.org/wiki/Ronald_Dale_Harris
Grady Player

3
有关为何如此重要的问题,请参见有关在线扑克游戏缺少真正随机性的这篇文章。
Varaquilex 2014年

1
如果您仅保留0-5个计数器并相应地掷骰子,即666亿次,您也将获得均等的分布。
jcora 2014年

Answers:


1384

让我们玩一些计算机扑克,只有您,我和我们都信任的服务器。服务器使用伪随机数生成器,该伪随机数生成器在播放之前就已使用32位种子进行了初始化。因此,大约有40亿个可能的套牌。

我手里有五张牌-显然我们不在玩Texas Hold'Em。假设发给我一张,给您一张,给我一张,给您一张,依此类推。所以我在甲板上有第一张,第三张,第五张,第七张和第九张卡。

早些时候,我对每个种子随机运行了40亿次伪随机数生成器,并将为每个种子生成的第一张卡记入数据库。假设我的第一张牌是黑桃皇后。那只是在所有这些可能的套牌中的52个中出现了第一张牌,因此我们将可能的套牌从40亿张减少到了大约8000万张。

假设我的第二张牌是三颗心。现在,我使用产生黑桃皇后的8000万个种子作为第一个数字,再运行8000万次RNG。这花了我几秒钟。我写下所有产生三颗心的牌组作为第三张牌-我手上的第二张牌。这又只是大约2%的套牌,所以现在我们只有200万套套牌。

假设我手中的第三张牌是7个俱乐部。我有一个200万种子的数据库,可以分发我的两张卡片;我再次运行RNG 200万次,以发现产生7个俱乐部的卡组的2%作为第三张牌,而现在只有4万个卡组。

您会看到这种情况。我再运行40000次RNG,以查找产生我的第四张牌的所有种子,这使我们下降到800个牌组,然后再运行800次,获得约20个产生我的第五张牌的种子,现在我只是生成那二十副牌,我知道您有二十只手中的一张。而且,我对接下来要画的东西有很好的主意。

现在您知道为什么真正的随机性很重要吗?在描述它的方式上,您认为分布很重要,但是分布并不是使过程随机化的原因。 不可预测性是使过程随机化的原因。

更新

根据评论(由于其非建设性的性质,现已删除),至少有0.3%的阅读者对我的观点感到困惑。当人们反对我没有提出的观点时,或更糟的是,我以我没有提出的观点为由确实提出的观点进行辩论,那么我知道我需要更清楚,仔细地解释。

单词分配似乎有些混乱,因此我想仔细指出用法。

手头的问题是:

  • 伪随机数和真正的随机数有何不同?
  • 为什么差异很重要?
  • 差异是否与PRNG的输出分布有关?

让我们首先考虑一种完美的方式来生成随机的纸牌来玩扑克。然后,我们将了解其他用于生成牌组的技术有何不同,以及是否有可能利用这种差异。

让我们首先假设我们有一个标记为的魔术盒TRNG。作为输入,我们给它一个大于或等于1的整数n;作为输出,它给我们一个真正的随机数,介于1和n之间(含)。盒子的输出是完全不可预测的(当给定一个数字而不是一个数字时),介于1和n之间的任何数字与另一个数字的可能性相同;也就是说,分布均匀的。(我们可以执行其他一些更高级的随机性统计检查;我忽略了这一点,因为它与我的论点无关。TRNG在假设上完全是统计随机性。)

我们从一副打牌的纸牌开始。我们要求在框内输入一个介于1到52之间的数字-即TRNG(52)。无论它返回多少数字,我们都会从已分类的牌组中算出那么多卡片,然后将其移除。它成为洗牌后的第一张牌。然后,我们要求TRNG(51)并执行相同的操作以选择第二张卡,依此类推。

另一种看待的方法是:有52个!= 52 x 51 x 50 ... x 2 x 1个可能的副牌,大约为2 226。我们实际上是随机选择的。

现在我们发卡。当我看我的卡片时,我什么都不知道。(除了显而易见的事实,就是您没有我拥有的任何牌。)它们可以是任何几率相等的牌。

因此,请确保我清楚地说明了这一点。我们对的每个输出都有统一的分配TRNG(n) ; 每个人都以1 / n的概率选择1到n之间的数字。同样,此过程的结果是我们选择了52个之一!用1/52的概率!,因此分布可能甲板通过所述一组可能的甲板的均匀。

好吧。

现在,假设我们有一个标记为的魔术盒PRNG。之前,你可以使用它,它必须接种有32位无符号数。

ASIDE:为什么要32?不能使用64位,256位或10000位数字作为种子吗?当然。但是(1)实际上,大多数现成的PRNG都是用32位数字播种的;(2)如果您有10000位随机性来进行种子播种,那么为什么要使用PRNG?您已经有10000位随机源!

无论如何,请回到PRNG的工作方式:将PRNG播种后,就可以像使用一样使用它TRNG。也就是说,您向其传递了一个数字n,它会返回一个介于1到n之间(包括1和n)的数字。而且,该输出的分布或多或少是均匀的。也就是说,当我们要求PRNG1到6之间的数字时,无论种子是什么,我们大约分别有六分之一的时间获得1、2、3、4、5或6。

我想多次强调这一点,因为它似乎使某些评论者感到困惑。PRNG的分布至少在两种方面是均匀的。首先,假设我们选择任何特定的种子。我们希望序列执行PRNG(6), PRNG(6), PRNG(6)...一百万次将产生1到6之间数字的均匀分布。第二,如果我们选择一百万个不同的种子并为每个种子调用PRNG(6) 一次,那么我们还将期望数字从1到均匀分布。 6. 在这两个操作中,PRNG的一致性与我描述的攻击无关

据说此过程是伪随机的,因为盒子的行为实际上是完全确定的。它根据种子从2 32种可能的行为中选择一种。也就是说,一旦播种,就会PRNG(6), PRNG(6), PRNG(6), ... 产生具有均匀分布的数字序列,但该序列完全由种子决定。对于给定的调用序列,例如PRNG(52),PRNG(51)...等,只有2 32个可能的序列。种子从本质上选择我们得到的种子。

为了生成一个牌组,服务器现在生成一个种子。(如何?我们回到这一点。)然后,他们调用PRNG(52)PRNG(51)依此类推,以生成套牌,与之前类似。

该系统容易受到我描述的攻击。要攻击服务器,我们首先要提前为自己的包装盒播种0并要求PRNG(52)并写下来。然后,我们用1重新种子,要求PRNG(52),并将其写下来,一直到2 32 -1。

现在,使用PRNG生成套牌的扑克服务器必须以某种方式生成种子。他们怎么做并不重要。他们可以要求TRNG(2^32)获得真正随机的种子。或者他们可以将当前时间作为种子,这几乎是随机的。我知道现在和你一样多。我攻击的重点是没有关系,因为我有数据库。当我看到第一张卡片时,可以消除98%的种子。当我看到第二张卡片时,我可以再消除98%,依此类推,直到最终我可以了解到少量可能的种子,并极有可能知道您手中的情况。

现在,我再次强调,这里的假设是,如果我们调用PRNG(6)一百万次每个数字将大约有六分之一的时间。该分布(或多或少)是均匀的,并且如果您只关心分布的均匀性,那就很好。问题的关键是我们关心的还有分布之外的其他事情PRNG(6)吗?答案是肯定的。我们也关注不可预测性

解决该问题的另一种方法是,即使分配100万个呼叫PRNG(6)可能很好,因为PRNG仅从2 32种可能的行为中进行选择,但它无法生成所有可能的数据包。 它只能生成2 226个可能的套牌中的2 32个。一小部分。因此,所有套牌的分布都很糟糕。但是同样,这里的根本性攻击是基于我们能够从一小部分输出中成功预测其过去和将来的行为。 PRNG

让我说这三次或四次,以确保它陷入。这里有三个分布。首先,分配产生随机32位种子的进程。这可能是完全随机的,不可预测的并且是统一的,并且攻击仍然有效。第二,分配给的一百万个电话PRNG(6)。这可以是完全统一的,并且攻击仍将起作用。第三,我已经描述了通过伪随机过程选择的牌组分布。这种分配非常差;只能选择IRL可能的套牌的一小部分。攻击取决于PRNG行为的可预测性,该行为是基于 PRNG 输出的部分知识而得出的

旁白:此攻击要求攻击者知道或能够猜测PRNG使用的确切算法是什么。这是否现实是一个悬而未决的问题。但是,在设计安全系统时,即使攻击者知道程序中的所有算法,也必须将其设计为可防止攻击。换句话说,为了使系统安全,必须保密的安全系统部分称为“密钥”。如果系统的安全性取决于您作为秘密使用的算法,则您的密钥包含这些算法。那是一个极其薄弱的职位!

继续。

现在,假设我们有第三个标记为的魔术盒CPRNG。它是的加密强度版本PRNG。它需要256位种子而不是32位种子。它具有PRNG种子从2 256种可能的行为之一中选择的属性。与我们的其他机器一样,它具有这样的属性:大量的调用CPRNG(n)会在1到n之间产生均匀的结果分布:每次发生的时间都是1 / n。我们可以对此进行攻击吗?

我们最初的攻击要求我们存储2 32个从种子到的映射PRNG(52)。但是2 256更大。CPRNG(52)多次运行并存储结果是完全不可行的。

但是,假设还有其他方法可以利用的价值CPRNG(52)推论出有关种子的事实吗?到目前为止,我们一直很笨,只是对所有可能的组合进行了暴力破解。我们可以看看魔术盒内部,弄清楚它是如何工作的,并根据输出推断出有关种子的事实吗?

否。细节太复杂,难以解释,但是CPRNG的设计巧妙,因此无论从多大的第一个输出或输出的任何子集推断出有关种子的任何有用事实都是不可行的。CPRNG(52)

好,现在让我们假设服务器正在使用它CPRNG来生成卡片组。它需要256位种子。它如何选择种子?如果它选择了攻击者可以预测的任何值,则突然,攻击将再次变得可行。如果我们可以确定2256种可能的种子中,服务器可能只选择了其中的40亿种,那么我们就重新营业了。我们可以再次发起这种攻击,只注意可能会生成的少量种子。

因此,服务器应确保256位数字均匀分布 -即,以1/2 256的概率选择每个可能的种子。基本上,服务器应该调用TRNG(2^256)-1来生成的种子CPRNG

如果我可以入侵服务器并查看服务器以查看选择了什么种子,该怎么办?在这种情况下,攻击者知道CPRNG的完整过去和将来。服务器作者需要防范这种攻击!(当然,如果我可以成功发起这种攻击,那么我可能也可以直接将钱转入我的银行帐户,所以也许那没那么有趣。要点是:种子必须是一个难以猜测的秘密,并且真正随机的256位数字非常难以猜测。)

回到我之前关于深度防御的观点:256位种子是此安全系统的关键。CPRNG的思想是只要密钥是安全的,系统就是安全的;即使知道该算法的所有其他事实,只要您可以保留密钥机密,对手的牌也是不可预测的。

好的,因此种子应该既是秘密的又要均匀分布,因为如果不是,我们可以发起攻击。我们假设,输出的分布CPRNG(n)是均匀的。那么在所有可能的套牌上的分布情况如何呢?

您可能会说:CPRNG输出2 256种可能的序列,但是仅有2 226种可能的套牌。因此,除了套牌之外,还有更多可能的序列,所以我们很好。现在,在该系统中,每个可能的IRL牌组(很有可能)都是可能的。这是一个很好的论据,除了...

2 226约为 52!。分开。2 256/52!不可能是整数,因为一件事就是52!被3整除,但没有2的幂!由于这不是一个整数,现在我们面临的情况是所有甲板都是可能的,但是有些甲板比其他甲板更有可能

如果不清楚,请考虑数字较小的情况。假设我们有3张卡,A,B和C。假设我们使用具有8位种子的PRNG,所以有256种可能的种子。有256种可能的输出,PRNG(3)具体取决于种子。因为256不能被3整除,所以没有办法让它们中的三分之一成为A,其中三分之一成为B,其中三分之一成为C。

同样,52不是均匀地分成2 256,因此在选择第一张纸牌时,某些纸牌必须存在一定的偏见,而与其他纸牌的偏见则一定存在。

在我们最初的带有32位种子的系统中,存在很大的偏差,并且绝大部分可能的平台都没有产生。在该系统中,可以生产所有甲板,但是甲板的分布仍然存在缺陷。有些甲板是非常轻微的比其他人更容易。

现在的问题是:我们是否有基于此漏洞的攻击?答案是在实践中,可能不是。CPRNG的设计目的是,如果种子是真正随机的,在计算上难以分辨出CPRNG和之间的区别TRNG

好,让我们总结一下。

伪随机数和真正的随机数有何不同?

他们表现出的可预测性水平不同。

  • 真正的随机数是不可预测的。
  • 如果可以确定或猜测种子,则所有伪随机数都是可预测的。

为什么差异很重要?

因为在某些应用程序中,系统的安全性依赖于不可预测性

  • 如果使用TRNG来选择每张卡,那么系统将无懈可击。
  • 如果使用CPRNG来选择每个卡,则如果种子既不可预测又未知,则系统是安全的。
  • 如果使用种子空间小的普通PRNG,则无论种子是不可预测的还是未知的,系统都不安全。足够小的种子空间容易受到我所描述的那种蛮力攻击。

差异是否与PRNG的输出分布有关?

分配或缺乏的均匀性个人电话RNG(n)不相关的我所描述的攻击。

正如我们所看到的,既PRNGCPRNG生产选择所有可能的甲板任何个人甲板的概率分布不佳。在PRNG相当糟糕,但两者都有问题。

还有一个问题:

如果TRNG比CPRNG好得多,而CPRNG又比PRNG好很多,为什么有人使用CPRNG或PRNG?

有两个原因。

第一:费用。TRNG 很贵。生成真正的随机数是困难的。对于任意多次调用,CPRNG都会产生良好的结果,而对于种子,仅一次调用TRNG。不利的一面当然是您必须保守该种子的秘密

第二:有时候我们想要可预测性,而我们关心的只是良好的分布。如果您生成“随机”数据作为测试套件的程序输入,并且它显示了一个错误,那么再次运行该测试套件会再次产生该错误将是很好的!

我希望现在更加清楚。

最后,如果您喜欢这种方法,那么您可能会喜欢一些有关随机性和置换的进一步阅读:


20
好吧,男孩和女孩。现在就足够了。如果您想进一步讨论这个问题,那就去聊天室kthnxbye吧!
Ivo Flipse'2

1
@Eric但是种子不会在每次新的套牌抽签之前重置,是吗?因此,虽然您是正确的,我们仅从相对较少的轨迹中进行采样,但您不知道当前您在轨迹中的确切位置并且轨迹相交。
AS


Knuth的TAOCP第2卷第3.5节“什么是随机序列?”(第149页)是对相关问题的一种很好的(但密集的)处理,首先从对等分布,k分布和∞分布的序列的定义开始。伪随机序列在3.5.F(p。170)中进行了讨论。另请参阅来自复杂性理论德国BSI的伪随机准则。
ShreevatsaR

160

正如埃里克·利珀特(Eric Lippert)所说,它不只是发行。还有其他测量随机性的方法。

早期的随机数生成器之一在最低有效位中具有序列-它交替使用0和1。因此,LSB是100%可预测的。但是,您不仅需要担心更多。每一位必须是不可预测的。

这是考虑问题的好方法。假设您正在生成64位随机性。对于每个结果,取前32位(A)和后32位(B),并在数组x [A,B]中建立索引。现在执行测试一百万次,对于每个结果,以该数字递增数组,即X [A,B] ++;

现在绘制一个2D图,其中数字越大,该位置的像素越亮。

如果确实是随机的,则颜色应为均匀的灰色。但是您可能会得到模式。以Windows NT系统的TCP序列号中的“随机性”图为例:

Windows NT

甚至是Windows 98中的这一类:

Windows 98

这是思科路由器(IOS)实施的随机性。 思科ISO

这些图由MichałZalewski的论文提供。在这种特殊情况下,如果可以预测一个系统的TCP序列号,则在与另一个系统建立连接时可以假冒该系统-这将允许劫持连接,截取通信等。即使我们无法100%地预测下一个数字,如果我们可以在我们的控制下创建新的连接,则可以增加成功的机会。当计算机可以在几秒钟内生成100,000个连接时,成功攻击的几率从天文数字变为可能甚至什至很可能。


30
这是如此辉煌,它使我流下了眼泪。应该有一个应用程序可以为每个操作系统(移动设备/桌面/服务器)和平台(JVM / Javascript / etc)创建这些应用程序。
HDave 2014年

5
Windows rand()函数非常好!它产生的云没有任何明显的模式。看看我的实现来尝试(和其他算法):github.com/Zalastax/visualize_random
Zalastax 2014年

93

虽然计算机生成的伪随机数对于计算机用户遇到的大多数使用情况都是可以接受的,但在某些情况下,需要完全不可预测的随机数。

在诸如加密之类的对安全敏感的应用程序中,伪随机数生成器(PRNG)可能会产生一些值,尽管它们在外观上是随机的,但实际上是攻击者可以预测的。如果使用了PRNG,并且攻击者掌握了PRNG的状态信息,则试图破解加密系统的人可能能够猜出加密密钥。因此,对于这样的应用,需要产生真正不可猜测的值的随机数生成器。请注意,某些PRNG被设计为具有密码安全性,并且可用于此类对安全性敏感的应用程序。

有关RNG攻击的更多信息,请参见此Wikipedia文章


9
存在密码PRNG,并且被广泛使用。它们可以从中等大小的种子中生成几乎无限的随机数流。将这种流与真正的随机数区分开来在计算上是不可行的,因此无法从这种流的任何部分获得额外的信息,并且出于任何实际目的,该数目与真实的随机数一样好。
aaaaaaaaaaaaaa 2014年

我认为解释此问题的最简单方法是必须对随机数生成器算法进行编程。这意味着要遵循一组指令。如果有一组指令,则不能是随机的。
Keltari 2014年

6
@Keltari您缺少熵的元素...大多数RNG(至少是加密RNG)从外部源(例如鼠标移动)收集输入并将其用作开始条件的一部分-因此,从A到的转换B已编程,但A(应该)的初始状态是不可猜测的。Linux /dev/random将大致估计可用的熵量,如果下降太低,则停止给出数字。
基本

出于好奇-为什么熔岩灯被认为是“真正随机的”?我知道它表现出相当不可预测的行为,但是对流体动力学以及这些流体在地球引力环境中如何相互作用具有足够把握的人肯定可以产生“可预测”的结果,不是吗?当然,熔岩灯是无法预测的,但对我来说,它们根本不是随机的,而是高度可预测的。
theGreenCabbage 2014年

1
@theGreenCabbage:我怀疑熔岩灯很乱。给定足够好的计算机模型和足够的精度,您可以(原则上)预测行为一段时间。但是,由于系统是混乱的,所以在初始条件下变化最小的两个熔岩灯会在行为上迅速发散。(并且此评论忽略了混沌吸引子。)
dmm

76

我在Python中尝试过:这是6000万次滚动的结果。最高变化约为0.15。这不是随机的吗?

实际上,它是如此“好”而又不好。...所有现有的答案都集中在给定一小序列初始值的可预测性上。我想提出另一个问题:

    您的分布的标准偏差要比随机滚动小得多

真正的随机性只是不来很接近平均“几乎完全超过1怎么过很多数字也可以选择”您使用的是作为质量的指示。

如果您查看有关多个骰子掷骰的概率分布的Stack Exchange问​​题,您将看到N个骰子掷骰的标准偏差的公式(假设真正的随机结果):

 sqrt(N * 35.0 / 12.0).

使用该公式,标准偏差为:

  • 1百万卷是1708
  • 6000万卷是13229

如果我们查看您的结果:

  • 1百万卷:stddev(1000066,999666,1001523,999452,999294,999999)是804
  • 6000万卷:stddev(9997653,9997789,9996853,10006533,10002774,9998398)是3827

您不能指望有限样本的标准偏差与公式完全匹配,但是应该非常接近。然而,在100万卷中,您所用的标准差还不到标准stddev的一半,而在6000万卷中,您还不到标准差的三分之一。

伪RNG倾向于在一系列不同的数字之间移动,从种子开始,在特定时期内不重新访问原始数字。例如,旧的C库rand()函数的实现通常具有2 ^ 32的周期,并且在重复种子之前,它们将只访问一次0到2 ^ 32-1之间的每个数字。因此,如果您模拟了2 ^ 32骰子掷出预模量(%)结果将包括从0到2 ^ 32的每个数字,每个1-6个结果的计数将是715827883或715827882(2 ^ 32并非6的倍数),因此标准偏差仅是零以上。根据上面的公式,正确的2 ^ 32卷标准偏差为111924。无论如何,随着伪随机卷数的增加,您将趋向于0标准偏差。当滚动数是该周期的很大一部分时,预计该问题将很严重,但是某些伪RNG可能会比其他伪RNG出现更严重的问题-甚至样本数量更少的问题。

因此,即使您不关心加密漏洞,在某些应用程序中,您也可能会关心分布没有过度,人为的结果。某些类型的模拟非常专门地试图计算出大量随机个体样本自然产生的不均匀结果的后果,但在某些pRNG结果中代表性不足。如果您要模拟大量人口对某个事件的反应,则此问题可能会从根本上改变您的结果,从而导致非常不准确的结论。


举一个具体的例子:假设一位数学家告诉扑克机器程序员,经过6000万次模拟掷骰-曾经在屏幕周围闪烁数百个小“灯光”,如果已经有10,013,229个或更多的6,则数学家期望距离均值1 stddev时,应该有少量支出。根据68–95–99.7规则(维基百科),这应该发生在大约16%的时间中(〜68%落在标准偏差内/只有一半以上在标准偏差内)。对于您的随机数生成器,这是来自均值上方约3.5个标准差的:0.025%的机会不到-几乎没有客户能获得此收益。请参阅刚才提到的页面上的“高偏差”表,特别是:

| Range    | In range   | Outside range | Approx. freq. for daily event  |
| µ ± 1σ   | 0.68268... | 1 in 3        | Twice a week                   |
| µ ± 3.5σ | 0.99953... | 1 in 2149     | Every six years                |

您在这里比较苹果和桔子。这两个标准偏差绝对无关。
Jbeuh 2014年

50

我只是写了这个随机数生成器来生成掷骰子

def get_generator():
  next = 1
  def generator():
    next += 1
    if next > 6:
      next = 1
    return next
  return generator

你这样用

>> generator = get_generator()
>> generator()
1
>> generator()
2
>> generator()
3
>> generator()
4
>> generator()
5
>> generator()
6
>> generator()
1

等等。您是否愿意将这个生成器用于运行骰子游戏的程序?请记住,它的分布恰好是您从“真正随机”生成器中获得的分布!

伪随机数生成器实际上具有相同的作用-它们生成具有正确分布的可预测数。它们之所以不好,与上述简单化的随机数生成器很糟糕的原因相同-它们不适合需要真正的不可预测性,而不仅仅是正确分布的情况。


2
“伪随机数生成器...生成具有正确分布的可预测数”-仅仅因为它是PRNG并不能保证它具有完美的分布(实际上,商业的PRNG并不能完全保证分布)这些答案中概述的原因)。尽管有足够的信息(使用的算法,起始种子,输出值,w / e)可以预测它们,但它们仍然存在差异。
Brian S

3
另外一点,我知道,但是get_generator = lambda: itertools.cycle(range(1,7))generator = get_generator()next(generator) # and so on是太优雅何况:)
剑锋Troelsen

2
@BrianS实际上,根据定义,经过一段时间的分配测试失败的PRNG是可以预测的。因此,在某个较大的N上,如果您在N次掷硬币中从N / 2个筹码中走了几步,您就可以开始押注筹码,并且您赢了比输了更多。同样,如果您获得了正面与反面的完美分布,但是正面总是成对出现,那么您将再次获得制胜法宝。通过分布测试,您可以了解PRNG的好处。
乔恩·基帕斯基

1
你忘了nonlocal next:-)。
科斯

5
甚至更好的例子是:Pi被认为是正常的,这意味着在任何基数中任何给定长度的数字序列出现的频率都比该基数中该长度的任何其他序列的出现频率低。从长远来看,从长远来看,当要求n个随机位时,采用pi 的下n个位并将其返回(“种子”是您开始的位)的算法。但是您仍然不希望生成器使用它-知道您生成的最后一堆位的人可能会发现该序列第一次出现,并假设您的种子在那里并且可能是正确的。
cpast 2014年

26

您的计算机可以执行的随机数生成适合大多数需求,并且您不太可能需要真正的随机数。

真正的随机数生成有其目的。在计算机安全,赌博,大型统计抽样等方面

如果您对随机数的应用感兴趣,请查阅Wikipedia文章


12
最大的问题是,当您需要攻击者出于安全原因无法预测的随机数时。
David Schwartz 2014年

16
您肯定会在需要一个真正的随机数的时候遇到麻烦。打开以https://... 开头的网页就足够了
Jan Hudec

3
@JanHudec:嗯,在日常使用中,打开任何程序时都需要安全的随机数,正好在您输入地址栏之前:请参阅地址空间布局随机化。这就是为什么发生这种情况的原因。
2014年

5
@JanHudec我的意思是要使用在线随机数生成器。真正的随机数经常使用,但是实际上很少有人需要自己生成它们。
Alex McKenzie 2014年

2
老虎机也使用PRNG,而不是TRNG。生成器一直运行,并在按下旋转按钮的确切时间选择一个数字。PRNG和真正的随机按钮按下时间之和等于TRNG。
罗杰·达尔2014年

26

大多数编程语言中由典型函数生成的随机数并非纯粹是随机数。它们是伪随机数。由于它们不是纯粹的随机数,因此可以用先前生成的数字的足够信息来猜测它们。因此,这将是加密安全性灾难

例如,下面使用的随机数生成器函数glibc不会生成纯粹的随机数。由此产生的伪随机数可以猜测。这是安全问题的大错。有这种灾难性的历史。不应在加密中使用它。

glibc random():
    r[i] ← ( r[i-3] + r[i-31] )  % (2^32)
    output  r[i] >> 1

这种类型的伪随机数生成器永远不应该在安全敏感的地方使用,即使在统计学上非常重要。

对伪随机密钥的著名攻击之一是对802.11b WEP的攻击。WEP具有104位的长期密钥,并与24位的IV(计数器)连接以构成128位的密钥,然后将其应用于RC4算法以生成伪随机密钥。

( RC4( IV + Key ) ) XOR (message)

这些键彼此紧密相关。在此,每一步仅将IV增加1,其他所有步保持不变。由于这并非纯粹是随机的,因此是灾难性的,很容易分解。通过分析大约40000帧即可恢复密钥,这只需几分钟。如果WEP使用纯随机的24位IV,则直到大约2 ^ 24(近1,680万)帧之前,它才是安全的。

因此,在可能的情况下,应该使用纯随机数生成器解决安全敏感问题。


3
我会把WEP的问题归咎于使用弱密码而设计不良的协议。使用现代流密码,您可以将计数器用作IV。
CodesInChaos 2014年

2
WEP的主要问题是在2 ^ 24(近1600万)帧中重复密钥。相关密钥甚至更糟,这使得在大约40000帧中破解代码成为可能。这里的重点是密钥不是随机的。它密切相关,因此很容易破解。
Prabhu 2014年

1
仅当生成加密密钥时,伪随机性在加密中才是不好的。除此之外,还可以。确实,RC4只是一个伪随机数生成器,其种子是将密钥XOR的128位扩展扩展到消息的明文上。
马特

12

不同之处在于伪随机数生成的数字在一段时间后是可预测的(重复),而真正的随机数不是。重复的长度取决于用于生成种子的种子的长度。

这是有关该主题的非常不错的视频:http : //www.youtube.com/watch?v=itaMNuWLzJo


可预测性!=重复。Mersenne Twister就是一个很好的例子。在624 Int32之后的大多数实现中,您都可以预测所有下一个数字,但是Mersenne Twister序列比该序列长得多(2 ^ 19937-1)。
2014年

我不明白为什么这个答案没有被推高,因为在我看来,这至少是部分问题的准确而简洁的答案。伪随机数可以在一些抽签之后容易地预测,抽签的数量随伪随机算法“质量”而变化。选择一种“好的”算法要着眼于以下方面:1.以相等的频率(分布)绘制每个值; 2.花费很长的时间才能重新开始序列,并再次从图中开始绘制相同的数字。相同的顺序。
2014年

“真正的随机数不是[可预测的]”。今天,这是真的。现在,如果我们相信“大爆炸”理论,并且有足够的能力根据物理原理在BB之后的任何时间计算宇宙的状态,那么我们就能预测未来,包括以下事实:我正在写这个非常准确的评论。对?
分钟

假设是正确的,但是考虑到人体实际动作所涉及的熵的巨大程度,所需的计算能力将非常可观。想想计算机覆盖的大洲。另外,由于依赖于先前的状态,因此需要存储宇宙中每个时间点上每个身体的状态,根据定义,这将需要比宇宙中可用的空间更多的空间,并且该空间完全充满了存储设备
TheEnvironmentalist

@TheEnvironmentalist-啊!“计算机覆盖的大陆” ...不是《银河旅行者指南》的全部内容吗?;-)
ysap

10

假设在生成伪随机数之前任何人都可以猜到它。

对于微不足道的应用程序,伪随机性很好,就像您的示例一样,您将获得大约正确的百分比(大约是总结果集的1/6),并且会有一些细微的变化(您将看到是否掷骰子600k)次);

但是,当涉及到计算机安全性时;真正的随机性是必需的。

例如,RSA算法首先从计算机选择两个随机数(P和Q)开始,然后对这些数字执行几个步骤以生成称为公用密钥和专用密钥的特殊数字。(私钥的重要部分是它是私钥,其他人都不知道!)

如果攻击者知道您的计算机将要选择的两个“随机”数字,则他们可以执行相同的步骤来计算您的私钥(其他人不应该知道的那个!)

攻击者可以使用您的私钥来做以下事情:a)与您的银行假装自己说话,b)听取您的“安全”互联网流量并对其进行解码,c)您与互联网上其他各方之间的伪装。

这就是需要真正的随机性(即无法猜测/计算)的地方。


10

我曾经使用的第一个随机数具有任何两个连续随机数的出色特性,第二个随机数更大,概率为0.6。不是0.5。第三个大于第二个,概率为0.6,依此类推。您可以想象模拟会如何造成破坏。

某些人甚至不相信我,即使随机数均等分布,这也是可能的,但是如果您看一下序列(1、3、5、2、4、1、3、5、2、4, ...)其中两个数字中的第二个以0.6的概率较大。

另一方面,对于仿真,能够重现随机数可能很重要。假设您进行了流量模拟,并想了解您可能采取的某些措施可以改善流量。在这种情况下,您希望能够通过尝试改善交通状况的不同操作来重新创建完全相同的交通数据(例如试图进入城镇的人)。


8

简短的答案是,通常人们出于一个不好的原因而要求“真正的随机性”,即他们不了解密码学。

一旦向它们提供了一些不可预测的比特,诸如流密码CSPRNG之类的密码原语就会产生大量不可预测的比特流。

细心的读者现在将意识到这里存在一个引导问题:我们必须收集一些熵才能开始所有这一切。然后be可以将它们提供给CSPRNGCSPRNG将愉快地提供我们需要的所有不可预测的位。因此,需要硬件RNG来播种CSPRNG。实际上,这是唯一需要熵的情况。

(我认为这应该已经发布在“安全性”或“密码学”中。)

编辑:最后,必须选择一个随机数生成器,该生成器足以满足预期的任务,就生成随机数而言,硬件不一定等同于良好的生成器。就像不良的PRNG一样,硬件随机源通常会有偏差。

编辑:这里的某些人假设使用一种威胁模型,攻击者可以在其中读取CSPRNG的内部状态,然后得出结论:CSPRNG不是安全的解决方案。这是不良线程建模的一个示例。如果攻击者拥有您的系统,那么游戏已经结束,简单而简单。此时您使用TRNG还是CSPRNG都没有任何区别。

编辑:所以,总结所有这些...熵是播种CSPRNG所必需的。一旦完成,CSPRNG将比我们(通常)收集熵快得多的速度提供安全应用程序所需的所有不可预测的比特。如果不需要不可预测性(例如,对于模拟),梅森扭曲器将以更高的速率为数字提供良好的统计特性。

编辑:任何愿意了解安全随机数生成问题的人都应该阅读以下内容:http : //www.cigital.com/whitepapers/dl/The_Importance_of_Reliable_Randomness.pdf


2
这不一定是安全问题。我认为有理由使用不涉及安全性的真正随机数。如果我正在进行一些依赖于随机数的科学研究,并且无论出于何种原因至关重要,那么数字都应尽可能地随机,那么我当然会利用硬件RNG,以便我可以放心,观察到的任何属性都不应该归因于RNG的怪癖。
Kef Schecter 2014年

3
@KefSchecter他们听到的硬件PRNG通常具有偏差和/或相关的输出。他们需要后处理步骤才能将其转换为统一的独立输出。没有理由相信此后处理步骤比现代流密码更可靠。我当然会更信任流密码。作为额外的奖励,它是可重现的,这在科学中很有价值。
CodesInChaos

好,可以。但是,难道不是同样适用于密码学应用程序吗?即使是这里的gievn回答,您也需要硬件RNG来播种CSPRNG。
Kef Schecter 2014年

2
@KefSchecter是的,加密应用程序需要真实的随机数来播种CSPRNG。但是对于其他所有内容,我们都可以使用该CSPRNG。
CodesInChaos 2014年

@KefSchecter:加密应用程序要求流不能被整个世界复制。相比之下,在科学应用中,能够证明一个人正在使用的“随机”数字不是简单地被选择来很好地展示自己的分析,这是有帮助的。例如,如果某人在宣布自己的方法后宣布将使用第二天的州彩票号码以某种方式生成数据,那么即使平日的图纸只有几打,读者也可以确信自己并没有对结果进行捏造熵位。
2014年

7

并非所有PRNG都适合所有用途。例如,Java.util.SecureRandom使用SHA1哈希,其输出大小为160位。这意味着可能有2160种可能的随机数流。就那么简单。内部状态值不能超过2 160。因此,你不能获得超过2个160 从一个单一的种子,不管你的种子是从哪里来的独特随机数的流。Windows CryptGenRandom被认为使用40字节状态,它具有2 320个可能的随机数流。

随机播放标准52张卡的副牌的方式为52 !,约为2 226。因此,无论播种如何,您都无法使用Java.util.SecureRandom来洗牌。它无法产生大约2 66种可能的混洗。当然,我们不知道他们是谁...

因此,如果我有256位真正随机性的来源(例如,来自Quantis RNG卡),则可以使用该种子为PRNG(如CryptGenRandom())播种,然后使用PRNG来整理牌。如果每次混洗都以真正的随机性进行播种,那会很好:不可预测且统计上是随机的。如果我对Java.util.SecureRandom做同样的事情,将可能无法产生洗牌,因为它无法以256位熵进行播种,并且其内部状态无法表示所有可能的洗牌。

请注意,java.util.SecureRandom结果将是不可预测的,并且在统计上是随机的。没有任何统计测试可以确定问题!但是RNG的输出不足以覆盖模拟一副纸牌所需的所有可能输出的整个域。

请记住,如果您添加了小丑,那就是54岁!您必须涵盖的范围,大约需要2 238种可能性。


2
您为什么要担心某些改组不会发生?这种限制没有明显的效果。
CodesInChaos 2014年

2
我对这个问题有些疑惑。对于监管严格的游戏公司,这种偏见将在数学上证明您使用计算机赢得纸牌游戏的机会与使用纸质纸牌时有所不同。机会的好坏并不重要。他们是不同的。该计算机在道德上并不等同于真实的卡座。此外,我们无法描述差异。面临严厉的监管罚款的博彩公司将非常关心。
Paco Hope

1
但这是可检测的。我使用一个已知过程对其进行检测:源代码审查和问题域知识。那是了不起的。我不能使用自动统计分析。它与使用java.util.Random或Mersenne Twister的用户一样可检测。统计分析不是RNG /问题域不匹配的唯一有效检测机制。根据定义,通过该检测器的失败不是成功。
Paco Hope

1
我从未不同意那句话。我所说的是,统计分析并不是RNG / PRNG正确无误的证明。这是一个假阴性的例子。它应该不正确,但是统计输出测试将通过它。如果我将SHA1(1),SHA1(2),SHA1(3)... SHA1(n)用作我的“ RNG”,这也将通过统计测试。这也是错误的。正确的定义超出了“通过统计检验”的定义。通过统计测试是必要的,但还不够。
Paco Hope

4
@CodesInChaos:“我们不知道可以利用绝大多数可能的IRL改组将永远不会发生的事实进行的攻击”的论点并不意味着这样的攻击是不可能的,只是我们没有不知道它是什么或如何防御它。在这种情况下,正确的态度是通过消除条件来消除攻击的可能性:制造足够质量的RNG,使其实际上可以生成所有可能的套牌。
Eric Lippert

6

伪随机数是使用数学函数和初始值(称为seed)生成的,而随机数不是。它们的可预测性使它们对于游戏重播非常有用,因为您只需要保存种子和玩家输入-AI每次都会以完全相同的“随机”方式做出响应。


6

“真实”随机数和“伪”随机数之间的差异是可预测性。该答案已经提供。

但是,正如大多数示例所示,可预测性并不一定是一件坏事。这是一个可预测性很好的罕见情况的实际例子:全球定位系统。

每个卫星使用适合于自动相关或互相关的不同的PRN码(Gold码),这对于信号传播时间的测量是必需的。对于这些戈德码,彼此之间的相关性特别弱,使得可以明确识别卫星,但允许通过发射序列与接收器之间的相关性进行距离计算。


2

为了快速检查随机性,您可以在[0; 1)中获取具有随机坐标的点,然后将其放入k维立方体中。然后执行将这个立方体切成子立方体的过程-必须按照众所周知的定理通过此过程正确测量子立方体(或子球体)的每个体积。

在您遇到的地方随机性的质量很重要...

  1. 安全目的。当您生成数字用作密钥生成的参数时,它是可以很好预测的-敌人会以100%的概率找到它,并使搜索范围小得多。

  2. 科学目的。在科学中,您不仅必须拥有处于良好状态的平均均值,而且还必须消除各种随机数之间的相关性。因此,如果采用(a_i-a)(a_ {i + 1} -a)并找到其分布,则它必须与统计信息相对应。

对相关性被称为“弱随机性”。如果要获得真正的随机性,则必须具有2个以上方差的高阶相关性。

今天,只有量子力学生成器才能提供真正的随机性。


1

为什么真正的随机性很重要?

基本上需要真正随机性的主要原因有两个:

  1. 如果您使用RNG进行加密(包括诸如真钱赌博和开彩票之类的事情),那么PRNG会使您的密码变得比您认为的数学分析(假设为TRNG)弱得多。PRNG实际上不是随机的,而是有一种模式-攻击者可以利用该模式来破解本应不可破解的密码。
  2. 如果您使用RNG模拟“随机”输入(例如,用于错误测试或模拟),则PRNG会使您的方法变弱。当您没有发现任何bug时,总会有一个令人困扰的疑问:是否存在我的PRNG模式不明显的bug,但是如果我仅使用TRNG就会出现?我的模拟发现是否准确地描述了现实,还是我发现的现象仅仅是PRNG模式的产物?

在这些区域之外,这并不重要。警告:如果您的PRNG非常非常糟糕,可能仍然不合适-您不想制作掷骰子总是连骰子都不能玩的掷骰子游戏,而您的玩家会不喜欢它。

Python的PRNG如何不够好?

通过使用这种简单的方法,您不太可能能够检测到实际PRNG的陷阱。RNG的统计分析本身就是科学领域,可以使用一些非常复杂的测试来对算法的“随机性”进行基准测试。这些比您的简单尝试要先进得多。

每个创建现实世界库的软件开发人员(例如Python开发人员)都将这些统计测试作为衡量标准,以查看其PRNG实现是否足够好。因此,除了实际的开发人员监督之外,您几乎不可能在实际的PRNG中轻松检测到模式。这并不意味着没有模式-PRNG从定义上就具有模式。


0

基本上,您无法通过对输出的数学分析来证明某源是随机的,您需要例如一个物理模型来说明该源是随机的(如放射性衰变)。

您可以运行批处理测试以在输出数据中找到统计相关性,在这种情况下,数据被证明是非随机的(但是随机源也可以具有非随机输出,或者如果不能给出特定的数据,则不是真正的随机)输出)。否则,如果通过测试,则可以说数据是伪随机的。

通过一些随机性测试仅意味着您具有良好的PRNG(伪随机数生成器),这对于不涉及安全性的应用程序很有用。

如果涉及安全性(例如,加密,生成密钥盐,用于赌博的随机数生成...),那么拥有良好的PRNG是远远不够的,它需要具有其他质量,例如不能轻易从先前的输出中猜出函数的输出,该功能需要具有理想的计算成本(要有足够的限制才能使用,但要足够高以克服强行尝试),运行该功能的硬件-或该设备(在今天很奇怪的情况下,它是一个模拟设备)-不应容易被篡改,等等。

拥有良好的PRNG可以在游戏中创建新的且不可预测的模式,以及在加密中非常有用-太麻烦了,无法在单个帖子中进行解释,只是以拇指的角色认为加密程序退出的过程应该是伪随机的,而不显示模式可以将先前的加密数据与随后的加密数据相关联,或将纯文本数据与加密数据相关联,或者将两个不同的密文彼此关联(因此可以对纯文本进行猜测)。


-5

短篇故事:

通过使用系统的当前微秒生成随机种子。

这个技巧很老了,仍然可以使用。

不包括暴力因素,我可以通过“下注”所有可能的数字来确定每种组合,这不是问题的重点,特别是当大多数随机数在使用前四舍五入时。

举个例子,我可以仅使用10个值来确定使用的种子。因此,知道了种子,我可以猜测下一个值。

如果我使用seed = 1,那么我可以获得下一个序列:

1、2、3、4、5、6、7、8、9 ...(然后我推断出种子使用id 1和下一个值10)

但是,如果每隔“ nth”个值更改一次发送,将会发生什么?将种子更改当前的微秒是一个便宜的技巧(也就是说,它不需要很多CPU周期)。

所以现在的顺序是:(种子= 1)1,2,3,4,5,(种子= 2),7,9,11,13 ...(15?)

在这种情况下:

a)我无法推断使用了哪种种子。

b)嗯,我猜不到下一个值。

c)我唯一能做的猜测就是推断下一个种子可能是一个大数。

无论如何,大多数现代随机生成器算法已经在后台使用了这种技巧。

真实的事实是,我们不需要量子计算机来创建“真实的”随机数,我们计算机的石英晶体的不精确性可以充当随机生成器,而且CPU的随机效率也是可变的,无需考虑CPU通常会同时执行多个任务。


2
这是一个非常糟糕的主意,它是需要真正无法预测的序列的漏洞的源头。如果花费微秒,则只有10 ^ 6的种子可能性很小。
2014年

@HoLyVieR:如果您关心安全性,那肯定是个坏主意,但并不像您看到的那样糟糕:系统启动(或unix epoch ...)以来通常使用微秒,这会大大增加可能的值范围。
mikera 2014年

1
@mikera并没有什么更好的,处理请求的时间是可以预测的。大量的密码重置功能是漏洞的向量。这些脚本使用您的技术生成了“随机”令牌,攻击者可以找到生成的令牌,因为发现执行令牌的时间相当琐碎……密码重置请求的发送时间为+-150ms。
2014年

当然,这种情况非常糟糕。但是,状态是在系统启动时播种的,而攻击者没有很好的猜测启动时间的方式的情况并没有那么糟糕。您可能很容易有10 ^ 12个可能的微秒可供选择,这会使某些类型的攻击不可行。需要明确的是:从加密角度来看,所有这些解决方案都非常糟糕,但是常量很重要
mikera 2014年

对于在线服务器,有时会公开提供系统正常运行时间信息。或者,您可以从状态页面“事件。再次启动服务器”中获取它。或者,您可以Ping,等待大量的停机时间,然后注意这可能是计算机重新启动(这将花费数亿时间检查,这相当少)。
Dereckson 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.