让我们玩一些计算机扑克,只有您,我和我们都信任的服务器。服务器使用伪随机数生成器,该伪随机数生成器在播放之前就已使用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)的数字。而且,该输出的分布或多或少是均匀的。也就是说,当我们要求PRNG
1到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)
不相关的我所描述的攻击。
正如我们所看到的,既PRNG
和CPRNG
生产选择所有可能的甲板任何个人甲板的概率分布不佳。在PRNG
相当糟糕,但两者都有问题。
还有一个问题:
如果TRNG比CPRNG好得多,而CPRNG又比PRNG好很多,为什么有人使用CPRNG或PRNG?
有两个原因。
第一:费用。TRNG 很贵。生成真正的随机数是困难的。对于任意多次调用,CPRNG都会产生良好的结果,而对于种子,仅一次调用TRNG。不利的一面当然是您必须保守该种子的秘密。
第二:有时候我们想要可预测性,而我们关心的只是良好的分布。如果您生成“随机”数据作为测试套件的程序输入,并且它显示了一个错误,那么再次运行该测试套件会再次产生该错误将是很好的!
我希望现在更加清楚。
最后,如果您喜欢这种方法,那么您可能会喜欢一些有关随机性和置换的进一步阅读: