加密安全随机数生成器如何工作?

时间:2010-03-15 18:44:33

标签: encryption random cryptography

我理解标准随机数生成器是如何工作的。但是当使用crytpography时,随机数确实必须是随机的。

我知道有些工具可以阅读cosmic white noise以帮助生成安全哈希,但是您的标准PC没有此功能。

加密安全的随机数生成器如何在没有可重复模式的情况下获取其值?

5 个答案:

答案 0 :(得分:107)

加密安全数字随机生成器,正如您可能用于生成加密密钥一样,通过从其他人无法观察到的源收集熵(即不可预测的输入)来工作。

例如,Linux上的/ dev / random(4)从硬件中断的时间变化中收集信息,例如硬盘返回数据,按键和传入网络数据包。这种方法是安全的,只要内核不会高估它收集了多少熵。几年前,来自各种不同来源的熵估计都减少了,使得它们更加保守。这是一个explanation of how Linux estimates entropy

以上都不是特别高的吞吐量。 / dev / random(4)可能是安全的,但是一旦无法确定数据是否安全随机,它就会通过拒绝提供数据来维护安全性。例如,如果您想生成 lot 加密密钥和随机数,那么您可能需要使用硬件随机数生成器。

硬件RNG通常是根据一对振荡器之间的差异进行采样而设计的,这对振荡器以接近相同的速度运行,但其速率根据热噪声略有变化。如果我没记错的话,用于英国优质债券抽奖的随机数发生器ERNIE就是这样做的。

替代方案包括对CCD上的噪声进行采样(请参阅lavaRND),放射性衰变(请参阅hotbits)或大气噪声(请参阅random.org,或者只是插入调谐到某处的AM收音机除了一个站到你的声卡)。或者您可以直接询问计算机用户bang on their keyboard like a deranged chimpanzee一分钟,无论您的船是什么漂浮。

正如安德拉斯指出的那样,我只想谈谈一些最常见的熵收集方案。 Thomas Pornin's answerJohannes Rössel's answer两者都做了很好的工作,解释了人们如何能够控制聚集的熵,以便再次将其中的一部分用掉。

答案 1 :(得分:50)

出于加密目的,需要的是流应“在计算上与均匀随机位无法区分”。 “计算”意味着它不需要是真正随机的,只有在没有访问上帝自己的计算机的情况下才会出现。

实际上,这意味着系统必须首先收集一系列 n 真正的随机位。 n 应足够大以阻止穷举搜索,即尝试 n 位的所有 2 ^ n 组合是不可行的。就今天的技术而言,这是实现的,只要 n 大于90左右,但密码学家只是两个人的权力,所以习惯于使用 n = 128

这些 n 随机位是通过收集“物理事件”获得的,就物理而言,这些事件应该是不可预测的。通常,使用时序:CPU有一个周期计数器,每秒更新数十亿次,有些事件发生不可避免的抖动量(传入网络数据包,鼠标移动,击键......)。系统对这些事件进行编码,然后通过应用加密安全散列函数(例如SHA-256)来“压缩”它们(然后截断输出以产生我们的 n 位)。这里重要的是物理事件的编码具有足够的:粗略地说,所述事件可以共同假设至少 2 ^ n 组合。根据其定义,散列函数应该很好地将该熵集中到 n 位字符串中。

一旦我们有 n 位,我们使用PRNG(伪随机数生成器)根据需要生成多个位。如果PRNG假设它在足够宽的未知 n 位密钥上操作,则其输出在计算上与均匀随机位无法区分,则称其为加密安全的。在90年代,一个流行的选择是RC4,它实现起来非常简单,速度非常快。然而,事实证明它具有可测量的偏差,即它并不像最初所希望的那样难以区分。 eSTREAM Project包括收集PRNG的新设计(实际上是流密码,因为大多数流密码包含在PRNG中,其输出与要加密的数据进行异或),记录它们,并促进密码学家的分析。 eSTREAM产品组合包含七个PRNG设计,这些设计被认为足够安全(即他们拒绝分析,而密码学家倾向于很好地理解他们拒绝的原因)。其中,四个是“针对软件进行优化”。好消息是虽然这些新的PRNG似乎比RC4更安全,但它们也明显更快(我们这里谈论的是每秒数百兆字节)。其中三个是“免费使用”,并提供源代码。

从设计的角度来看,PRNG重用了分组密码的大部分元素。使用相同的雪崩和比特扩散到宽内部状态的概念。或者,可以使用分组密码构建一个不错的PRNG:只需使用 n 位序列作为密钥进入分组密码,并加密计数器的连续值(表示为 m < / em> -bit序列,如果分组密码使用 m -bit块)。这产生了伪随机比特流,只要分组密码是安全的,并且产生的流不长于 m * 2 ^(m / 2)比特,这在计算上无法与随机区分开来。 (对于 m = 128 ,这意味着大约300亿千兆字节,因此对于大多数用途而言足够大)。这种用法称为counter mode (CTR)

通常,CTR模式下的分组密码不如专用流密码快(流密码的点是,通过丧失分组密码的灵活性,预期会有更好的性能)。但是,如果碰巧有一个来自英特尔的最新CPU带有AES-NI指令(基本上是硬件中的AES实现,集成在CPU中),那么具有CTR模式的AES将产生无与伦比的速度(几个每秒千兆字节)。

答案 2 :(得分:16)

首先,加密安全PRNG的重点是而不是来生成完全不可预测的序列。正如您所指出的那样,缺少产生大量(或多或少)真实随机性 1 的东西使得这种情况变得不可能。

所以你选择只有 hard 的东西来预测。 “硬”在这里意味着,无论如何,无论何时需要它都会花费不可思议的长时间。有许多数学算法可以参与其中 - 如果您采用一些着名的CSPRNG并查看它们的工作原理,您可以一瞥。

构建此类PRNG的最常见变体是:

  • 使用流密码,该密码已经输出(假定安全的)伪随机比特流。
  • 在计数器模式下使用分组密码

有时也会使用计数器上的哈希函数。维基百科有more on this

一般要求只是从发生器的比特流中确定原始初始化向量并且不能轻易预测下一个比特是不可行的。

对于初始化,大多数CSPRNG使用系统上可用的各种源,范围从线路噪声,中断或系统中的其他事件等真正随机的事物到诸如某些存储器位置之类的其他事物,&amp; c。初始化矢量最好是随机的,不依赖于数学算法。在Debian的OpenSSL实现中,这种初始化被破坏了一段时间,这导致了严重的安全问题。


1 其中也存在问题,必须小心消除偏差,因为热噪声等因素根据温度而具有不同的特性 - 您几乎总是偏向并需要消除它。这本身并不是一项微不足道的任务。

答案 3 :(得分:6)

为了使随机数生成器被认为是加密安全,需要保护其免受知道算法和(大量)先前生成的比特的攻击者的攻击。这意味着拥有该信息的人无法重建发生器的任何隐藏内部状态,并以低于50%的准确度预测下一位产生的内容。

正常的伪随机数生成器通常不具有加密安全性,因为从先前输出的位重建内部状态通常是微不足道的(通常,整个内部状态只是直接产生的最后N位)。任何没有良好统计特性的随机数生成器也不具有加密安全性,因为即使不知道内部状态,其输出至少也是可预测的。

因此,关于它们如何工作,任何好的加密系统都可以用作加密安全的随机数发生器 - 使用加密系统来加密“正常”随机数发生器的输出。由于攻击者无法重建普通随机数发生器的明文输出,因此无法直接攻击它。这是一个有点循环的定义,引出了如何密钥加密系统以保证其安全的问题,这是另一个问题。

答案 4 :(得分:5)

每个生成器都会使用自己的播种策略,但这里有一点来自Windows API documentation on CryptGenRandom

  

使用Microsoft CSP,CryptGenRandom使用相同的随机数   其他安全组件使用的生成器。这允许很多   促进系统范围种子的过程。 CryptoAPI存储了一个   每个用户的中间随机种子。为了形成种子   随机数生成器,一个调用应用程序提供它可能的位   例如,鼠标或键盘定时输入 - 然后   结合存储的种子和各种系统数据和用户   进程ID和线程ID,系统时钟等数据   系统时间,系统计数器,内存状态,可用磁盘集群,   散列用户环境块。这个结果用于播种   伪随机数发生器(PRNG)。

     

在带有Service Pack 1(SP1)及更高版本的Windows Vista中,   在NIST中指定的基于AES计数器模式的PRNG的实现   使用特殊出版物800-90。在Windows Vista中,Windows Storage   Server 2003和Windows XP,联邦信息中指定的PRNG   使用处理标准(FIPS)186-2。如果应用程序有权访问   对于一个好的随机源,它可以用一些填充pbBuffer缓冲区   调用CryptGenRandom之前的随机数据。然后,CSP使用此数据   进一步随机化其内部种子。可以省略   在调用之前初始化pbBuffer缓冲区的步骤   CryptGenRandom。