为什么我们不合并随机数生成器?


60

在许多应用中使用伪随机数生成器。因此人们实施了他们认为很棒的方法,后来才发现它有缺陷。最近,JavaScript随机数生成器发生了这种情况。RandU也早得多。还存在诸如Twister之类的不当初始播种的问题。

我找不到任何人将两个或多个生成器族与通常的xor运算符结合在一起的示例。如果有足够的计算机功能来运行java.SecureRandom或Twister实现之类的东西,为什么人们不将它们结合起来?ISAAC xor XORShift xor RandU应该是一个很好的例子,在这里您可以看到单个发电机的弱点正在被其他发电机减轻。由于内在算法完全不同,因此还应有助于将数字分配到更高的维度。是否有一些不应该将它们结合在一起的基本原则?

如果您要构建一个真正的随机数生成器,人们可能会建议您结合使用两个或多个熵源。我的例子不同吗?

我排除了几个线性反馈移位寄存器来自同一家族的共同示例。


答案可能取决于应用程序。您想使用伪随机序列做什么?
Yuval Filmus

1
您是否已找到Fortuna(en.wikipedia.org/wiki/Fortuna_%28PRNG%29),听起来像您所描述的那样,它将各种随机源集合为一个。
小码

1
@LittleCode实际上听起来完全不同。Fortuna从单个哈希函数输出数据。在通过单个输出函数(重新)将其散列之前,它只是与许多弱的熵收集机制混为一谈。我的问题与从几个函数输出(为什么不是10个函数)有关?如果这是一个填充设备,则速度无关紧要。
保罗·乌萨克

1
已故的PRNG领域的著名研究者George Marsaglia发明了多种新型PRNG类型,例如带乘乘和异或移位,他在1990年代提出了将三个PRNG结合在一起的KISS发生器时就做到了这一点。不同类型的。在过去的20年中,我一直成功地使用KISS,当然不是密码学。关于KISS的一个有用的辅助资源是Greg Rose2011年发表的这篇论文,他指出了组成PRNG之一的问题,这并没有使合并的概念无效
njuffa '16

4
Knuth涉及天真地组合伪随机数生成器(使用一个随机数选择要使用的生成器)的结果,该函数收敛到固定值!因此,在微型计算机革命之前的日子里,他警告我们不要混用随机发电机。
JDugugz

Answers:


7

IIRC(这是从内存中提取的),1955年兰德的畅销书《百万随机数字》做了这样的事情。在计算机价格便宜之前,人们从本书中选择了随机数。

作者生成了带有电子噪声的随机位,但事实证明这是有偏见的(很难使触发器在触发器和触发器上花费完全相同的时间)。但是,组合位使分布更加均匀。


45

当然,如果需要,可以将PRNG像这样组合,假设它们是独立播种的。但是,它会比较慢,并且可能无法解决人们遇到的最紧迫的问题。

实际上,如果您需要非常高质量的PRNG,则可以使用经过严格审查的加密强度PRNG,并使用真正的熵作为种子。如果执行此操作,则最有可能的故障模式不是PRNG算法本身存在问题。最有可能的失败模式是缺乏足够的熵(或者可能是实现错误)。将多个PRNG异或对这种故障模式没有帮助。因此,如果您想要高质量的PRNG,则对它们进行异或处理可能没有什么意义。

另外,如果您希望统计PRNG足以用于仿真目的,通常#1的关注点是速度(真正快速地生成伪随机数)或简单性(不想在研究或实现上花费大量的开发时间)。Xoring会减慢PRNG的速度并使它更加复杂,因此它也不能满足该上下文中的主要需求。

只要您表现出合理的照料和能力,标准的PRNG便足够了,因此我们没有理由需要任何更高级的产品(无需异或)。如果您甚至没有最低限度的照料或能力,那么您可能就不会选择复杂的东西,例如异或,而改善状况的最佳方法是在选择PRNG时更加注重照料和能力而不是异或。

底线:基本上,xor技巧不能解决人们在使用PRNG时通常实际遇到的问题。


3
“缺乏足够的熵...对多个PRNG进行异或操作无济于事” –实际上,这可能会造成阻碍,因为您增加了为PRNG注入种子所需的熵。这就是为什么您不希望使其成为常规的方法来组合经过严格审查的PRNG,即使确实确实可以保护您免受那些经过审查的PRNG之一而变成完全垃圾(在您使用的实现中) 。
史蒂夫·杰索普

另一个原因是,实现错误远比算法的基本问题普遍得多,因此越简单越好。至少可以针对另一个实现或参考值测试标准算法,而定制的异或不能。
吉尔斯(Gilles)

1
@DW为什么“独立播种”?由于我的问题涉及不同发电机系列的组合,因此每个系列应从相同的种子产生唯一的输出序列。例如,可以很容易地从同一密钥中植入java.SecureRandom和RC4,然后进行组合。
保罗·乌萨克

1
@DW您声明的一个大假设是“使用经过严格审查的加密强度PRNG”。与大多数密码算法,散列等类似,现实是几乎无法确定的-随着时间的流逝,发现了弱点。他们因昨天或过去的知识而受到“严格审查”。
2016年

1
@PaulUszak,我认为我从来没有说过对两个生成器进行异或运算会使其更易于出现错误。我的意思是,如果您选择一个好的PRNG(仅一个),则最可能的故障模式之一是种子失败或实现失败,而对两个生成器进行异或运算都无济于事。(当然,如果单个PRNG没有失败,则对两个生成器进行异或运算也没有用。)因此,基本上,这是在解决错误的问题。换句话说,异或生成器并不能增加确定性,因为它不能解决不确定性的最重要原因。
DW

19

实际上,正是通过这种方式宣布了一些突破。

德克萨斯大学计算机科学教授David Zuckerman和博士生Eshan Chattopadhyay发现,可以通过组合两个“低质量”随机源来生成“高质量”随机数。

这是他们的论文: 显式两源提取器和弹性函数


8
尽管UT进行了PR的努力,但这是一篇关于不同主题的纯理论文章,绝对没有实际意义。
Yuval Filmus

4
@Yuval Filmus-您是否愿意扩大评论范围?
NietzscheanAI

8
理论与实践之间存在很大的分歧。通常,从业者不关心理论,反之亦然。在这种情况下,UT的PR分支决定锁定一篇出色的理论论文,将其描述为与实际相关,而并非如此。从实践的角度来看,本文中考虑的问题并不那么有趣,它们具有可以很好地起作用的简单解决方案,尽管无法证明它们确实可行。
Yuval Filmus

2
而且,该特定论文只是萃取器理论领域的一部著作。您可以用相同的方式向该地区的任何其他纸张开票。它们都是关于结合弱源创建强源。区别仅在于参数。
Yuval Filmus

3
最后,本文中的构造很可能是一个过大的矫饰,而不是您想实现的。这种类型的构造的具体参数很难确定,并且通常非常糟糕,因为论文始终关注渐近状态,而忽略常数。
Yuval Filmus

9

假设是伪随机二进制序列。也就是说,每个是支持的随机变量,并且变量不一定是独立的。我们可以认为此序列是通过以下方式生成的:首先,我们采样一个统一的随机密钥,然后使用一些函数生成伪随机序列。X1,,XnXi{0,1}X1,,XnKf(K)

我们如何测量伪随机序列有多好?尽管可以测量特定实现的质量(例如,使用Kolmogorov复杂度),但在此我将集中讨论取决于随机变量的整个分布的测量。熵就是一个这样的例子,但是我们只需要度量两个属性:(更大的意味着更随机的序列)X1,,Xn(X1,,Xn)LL()

  • 如果是确定性序列(即固定序列),则。大号X 1ÿ 1... X ÑŶ Ñ= 大号X 1... X Ñy1,,ynL(X1y1,,Xnyn)=L(X1,,Xn)

  • 如果是两个独立的伪随机序列,则是一个独立的随机位,并且,然后是。X0,X1T{0,1}Z=XTL(Z)min(X0,X1)

第一个属性表示在第位翻转后该度量不变。第二个属性意味着,如果我们混合两个分布,则结果至少与较差的结果一样好。iX,Y

任何合理的随机性度量都将满足第一个属性。第二性质通过最流行的度量来满足,例如熵和最小熵。HH

现在我们可以陈述并证明一个定理,表明对两个伪随机序列进行异或运算始终是一个好主意。

定理。令是两个相同长度的独立伪随机序列,而是允许的随机性度量(一个满足上述两个条件)。然后X,YL

L(XY)max(L(X),L(Y)).

证明。假设。然后是分布混合,并根据的分布进行混合。由于并且混合物至少与混合的最差分布一样好,因此我们得到。L(X)L(Y)XYXyYL(Xy)=L(X)L(XY)L(X) 

该定理的意思是,对于任何允许的随机性度量,如果对使用两个独立密钥生成的两个伪随机序列进行XOR ,则结果始终至少与被XOR的更好序列一样好。

实际上,为了使用两个独立的密钥,我们可能会以伪随机的方式将一个密钥扩展为两个密钥。因此,这两个键不是独立的。但是,如果我们使用“昂贵”的方式将一个键扩展为两个键,则我们期望得到的两个键“独立”“看”,因此定理将保持“道德”。在理论密码学中,有一些方法可以使此语句精确。


那么,我们应该对两个伪随机数生成器进行XOR吗?如果我们不受速度限制,那肯定是个好主意。但实际上,我们有速度限制。然后我们可以问以下问题。假设我们给了两个PRNG,每个PRNG的参数控制着发电机的运行时间(以及强度)。例如,可以是LFSR的长度,也可以是回合数。假设我们使用一个带参数 PRNG ,另一个带参数 PRNG ,然后对结果进行XOR。我们可以假设,因此总运行时间是恒定的。的最佳选择是什么TTT1T2T1+T2=tT1,T2?这里有一个折衷,通常很难回答。设置可能比或差得多。(t/2,t/2)(t,0)(0,t)

最好的建议是坚持使用流行的PRNG,这种PRNG坚固。如果您可以节省更多时间来生成序列,请使用独立密钥(或使用昂贵的PRNG扩展单个密钥生成的密钥)对多个副本进行XOR。


评论不作进一步讨论;此对话已转移至聊天。一旦达到建设性的目标,请编辑答案以合并讨论的结果。
拉斐尔

4

我会试一试,因为我对其他一些答案中的建议感到不安。

令是由两个RNG生成的无限位序列(不一定是一旦知道初始状态就可以确定的PRNG),我们正在考虑使用序列的可能性。,希望在某种意义上改善行为。与和相比,有很多不同的方式可以认为更好或更差;以下是一小部分,我认为是有意义,有用的,并且与“更好”和“更差”一词的正常用法保持一致:X,YXYXYXY

  • (0)序列真正随机的概率增加或减少
  • (1)可观察到的非随机性的概率会增加或减少(对于某些观察者,应用一定量的仔细检查,大概是这样)
  • (2)可观察到的非随机性的严重性/明显性增加或减少。

首先让我们考虑(0),这是三个希望精确的希望中的唯一一个。注意,实际上,如果两个输入RNG中的任何一个确实是真正随机的,无偏倚的并且彼此独立,则XOR结果也将是真正的随机且无偏倚。考虑到这一点,请考虑以下情况:您认为是真正的随机无偏隔离比特流,但您不确定。如果是您错了的概率,则不是真正随机的概率为 ,实际上少得多,因为X,YεX,εYXYεXεY<min{εX,εY}εX,εY假定非常接近0(“您认为它们是真正随机的”)。实际上,它甚至比这更好,我们还考虑了真正独立的可能性,即使它们都不是真正随机的: 因此,我们可以得出结论,在意义上(0),XOR不会造成伤害,并且可能会带来很大帮助。X,Y

Pr(XY not truly random)min{Pr(X not truly random),Pr(Y not truly random),Pr(X,Y dependent)}.

但是,对于PRNG来说(0)并不有趣,因为在PRNG的情况下,所讨论的序列都没有任何真正随机的机会。

因此,对于这个实际上与PRNG有关的问题,我们必须谈论诸如(1)或(2)之类的问题。由于这些是根据诸如“可观察的”,“严重的”,“明显的”,“表观的”之类的性质和数量而言的,因此我们现在谈论的是Kolmogorov的复杂性,而我将不尝试使其精确。但是,我将做出无可争议的断言,即“ 01100110 ...”(期间= 4)比“ 01010101 ...”(期间= 2)比“ 00000000 ...”(恒定)。

现在,人们可能会猜测(1)和(2)将遵循与(0)相同的趋势,因此结论“ XOR不会伤害”可能仍然成立。但是,请注意,和都不是非随机的,但它们之间的相关性却导致显然是非随机的。当然,最严重的情况是(或)时,在这种情况下是常数,在所有可能的结果中是最差的;通常,很容易看出,无论和多么出色,XYXYX=YX=not(Y)XYXYX和必须“接近”独立,以使它们的xor不可观察非随机。实际上,可以将不可观测的依赖合理地定义为是不可观测的非随机。YXY

事实证明,这种意外依赖是一个很大的问题。


出问题的一个例子

问题指出“我不排除几个线性反馈移位寄存器来自同一家族的共同示例”。但是我暂时将这种排除排除在外,以便给出一个非常简单的,真实的例子,说明XORing可能出错的事情。

我的示例将是大约在1983年的Unix版本上的rand()的旧实现。IIRC,rand()函数的这种实现具有以下属性:

  • 每次调用rand()的值都是15个伪随机位,即范围为[0,32767)的整数。
  • 连续的返回值交替奇偶校验;也就是说,最低有效位交替0-1-0-1 ...
  • 最低有效位的下一个是周期4,第二高位的下一个是周期8,因此最高位是周期。215
  • 因此,rand()的15位返回值的序列是周期性的,周期为。215

我一直无法找到原始源代码,但从https://groups.google.com/forum/#!topic/comp.os.vms/9k4W6KrRV3A中的几篇文章拼凑在一起它确实执行了以下(C代码),这与我对上面属性的记忆一致:

#define RAND_MAX 32767
static unsigned int next = 1;
int rand(void)
{
    next = next * 1103515245 + 12345;
    return (next & RAND_MAX);
}
void srand(seed)
unsigned int seed;
{
    next = seed;
}

可以想象,尝试以各种方式使用rand()会导致各种各样的失望。

例如,在某个时候,我尝试通过反复进行以下操作来模拟一系列随机硬币翻转:

rand() & 1

即最低有效位。结果是简单的交替-头-尾-头-尾。起初很难相信(必须是程序中的一个错误!),但是在我确信自己是对的之后,我尝试使用下一个最低有效位代替。如前所述,这并没有多大好处-该位是周期性的,周期为4。继续探索更高的位将揭示出我之前提到的模式:也就是说,每个下一个高阶位的周期是前一个周期的两倍,因此在所有这些中,最高位是最有用的。但是请注意,这里没有黑白阈值“ bit有用,bit没用”。我们真正能说的是带编号的比特位置具有不同程度的有用/无用。ii1

我还尝试了诸如进一步加扰结果或将从对rand()的多次调用返回的值进行XOR运算之类的事情。对连续的rand()值对进行异或运算当然是灾难,它导致所有奇数!出于我的目的(即产生“明显随机”的抛硬币序列),异或的恒定奇偶校验结果甚至比原始的交替奇偶行为差。

稍作其放入原始框架中:即是rand()返回的具有给定种子的15位值的序列,而是来自另一个种子的序列。再次,将是全偶数或全奇数的序列,这比原始的交替偶数/奇数行为差。XsXYsYXY

换句话说,通过任何合理的解释,这就是XOR使(1)和(2)的情况恶化的示例。在其他几种方面,情况也更糟:

  • (3)与XORed的最低有效位有明显的偏差,即0和1的频率不相等,这与两个输入中任何编号的位的位置都无偏的不同。
  • (4)实际上,对于每个位位置,都有成对的种子在该XOR结果中有该位位置有偏差,对于每对种子,有(至少5个)位位置有在XOR中有偏差。结果。
  • (5)XOR结果中整个15位值序列的周期为1或,而原始文件为。214215

(3),(4),(5)都不是显而易见的,但是它们都很容易验证。


最后,让我们考虑重新引入禁止来自同一家庭的PRNG。我认为这里的问题是,直到/除非有人开始使用XOR并注意到(或攻击者注意到)事情在(1)的意义上变得更糟,否则永远无法真正弄清两个PRNG是否来自“同一个家族”。 (2),即直到输出中的非随机模式越过阈值(从不被注意到注意到/尴尬/灾难)为止,这已经为时已晚。

我对这里的其他答案感到震惊,这些答案在理论方法的基础上给出了不合格的建议“ XOR不会伤害”,在我看来,在建模大多数人认为“好”和“坏”的工作上做得很差。现实生活中的PRNG。该建议与XOR使情况变得更糟的清晰明了的示例相矛盾,例如上面给出的rand()示例。尽管可以想象到,相对“强”的PRNG在与玩具rand()进行异或时,可以始终显示相反的行为,从而使它们成为一个好主意,但我没有看到在这个方向上的证据,无论是理论上的还是经验的,所以我认为这种情况似乎是不合理的。

就我个人而言,在我年轻时被XORing rand()所震惊,以及一生中无数其他各种各样的令人惊讶的关联,我几乎没有理由认为如果我再次尝试类似的策略,结果会有所不同。这就是为什么我本人不愿对多个PRNG进行异或运算,除非进行了非常广泛的分析和审核,以使我确信对于所涉及的特定RNG这样做可能是安全的。当我对一个或多个PRNG的信心不足时,作为一种潜在的解决方法,对它们进行异或运算不太可能增加我的信心,因此我不太可能将其用于此目的。我想您的问题的答案是,这是一种普遍持有的观点。


那么,您如何解释数十亿人使用A5 / 1的情况?
保罗·乌萨克

@PaulUszak我不知道。被数十亿人使用的A5 / 1是否与我所说的相矛盾?
唐·哈奇

它是三个钉(实际上是来自同一个家庭)在一起,以打扰和报警您的方式形成了更好的
alarm钉

令我不安和震惊的是不合标准的建议“如果不确定,请继续进行XOR和一堆RNG;这不会使情况变得更糟”。我并不是要说或暗示在所有情况下XOR都是不好的,而且我对A5 / 1或在其中使用XOR没有任何意见。如果我更改最后的愚蠢的摘要语句以使其更清楚,这会有所帮助吗?
唐·哈奇

1
最后,我用更真实,希望减少误导的东西代替了简单的“对XORing RNG拒绝回答”。
唐·哈奇

0

免责声明:这个答案严格来说是关于“我们没有做到这一点”,而不是“这是为什么或不起作用的数学证明”。我并不声称XOR会(或不会)引入任何加密漏洞。我的观点是,经验告诉我们,即使是最简单的方案也几乎总是会带来无法预料的后果-这就是为什么我们避免使用它们。

对于RNG和PRNG,“随机性”只是冰山一角。还有其他重要的品质,例如均匀性。

想象一个普通的骰子,它本身就是一个很好的RNG。但是,现在让我们说您需要1-5而不是1-6的范围。首先想到的是简单地擦除6张面并将其替换为多余的1张。“随机性”仍然存在(结果仍然是真正随机的),但是均匀性却受到很大的损害:现在1的可能性是其他结果的两倍。

多个RNG的结果合并起来也是类似的滑坡。例如。简单地添加2个骰子就可以完全消除一致性,因为“ 7”的可能性是“ 2”或“ 12”的6倍。我同意XOR乍看起来比加法好,但是在PRNG中,乍一看没有任何结果。

这就是为什么我们倾向于坚持已知的实现的原因-因为有人花了大量的时间和金钱来研究它们,并且所有缺点都是众所周知的,可以理解的并且可以解决。推出自己的产品时,您可能会创建漏洞,并且应该付出类似的努力来证明它。正如骰子添加示例所示,合并与从头创建新的骰子没有太大区别。

安全是一条链,与最弱的部分一样强大。安全方面的一条经验法则:每当结合两件事时,通常会得到一些缺陷,而不是优势。


7
强烈反对。如果将真正的随机序列与任意序列进行异或运算,您仍然会得到真正的随机序列。同样,如果您对两个独立的伪随机序列(即,使用不同的密钥生成)进行XOR,则得到的强度至少与每个独立的伪随机序列一样强。
Yuval Filmus

3
对我来说这似乎是错误的。这里的通常情况是,我认为我有两个非常高质量的RNG,它们产生的确是真正随机的比特,但是有一个很小的机会,我可能会(也许是严重地)误认为其中的一个(或者更可能是两个)。如果我将它们异或在一起,只要我对至少其中之一是正确的,结果将是真正随机的,我很好。因此,通过将它们组合在一起,我将不良RNG的机会从大约epsilon / 2减少到极小的epsilon ^ 2,这绝对是一次胜利。我怀疑即使在不那么尝试的情况下,类似的动力仍然存在。
唐·哈奇

2
我仍然不相信。当我写“真正随机”时,我的意思是“均匀随机”。如果您将均匀随机序列与任意序列进行异或运算,则会得到均匀随机序列。
Yuval Filmus

2
@DonHatch当然可以了。假设您的PRNG生成了一个长度为100的序列,然后是相同序列的嘈杂版本,依此类推。假设第二个副本与第一个副本的按位相关性是。序列满足。由于,可以这样说,相关性并未“大幅度放大”,而是显着降低了。Pr[Xi+100=Xi]=(1+ϵ)/2Zi=XiYiPr[Zi+100=Zi]=(1+ϵ2)/2ϵ2|ϵ|
Yuval Filmus

3
@YuvalFilmus您可能是正确的,项目i与项目i + 100之间的相关性已大大降低,但这不是重点。对于一个非常具体且真实的示例:我记得unix上旧的糟糕的rand()实现在返回的每个31位整数的最低位中都有周期性的行为,大多数人没有注意到。将不幸的移位大小与其本身的移位副本(这是您使用其他种子时得到的结果)的整数序列进行异或运算,您将得到所有偶数。在大多数情况下,这比原始顺序中的问题糟糕得多。
唐·哈奇
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.