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


68

我了解标准随机数生成器的工作原理。但是当使用密码术时,随机数确实必须是随机的。

我知道有些仪器可以读取宇宙白噪声以帮助生成安全的哈希,但是您的标准PC却没有。

密码安全的随机数生成器如何获得没有可重复模式的值?


5
没有真正的随机数:)
汤姆(Tom)2010年

23
@汤姆:关于贝尔不等式的许多实验结果清楚地表明,量子随机性要么是真的随机,要么由于非局部性而真是不可知。因此,出于所有意图和目的,都有随机数。
dmckee ---前主持人小猫,2010年

4
@汤姆:...只有无法理解的事情。:)(...对于我7岁的孩子,对数确实是随机的。:)
Andras Vass 2010年

2
@Tom:random.irb.hr-注册时请注意验证码。:)“我们使用'Quantum Random Bit Generator'(QRBG121),这是一种快速的不确定性随机位(数字)发生器,其随机性取决于半导体中光子发射的量子物理过程的固有随机性以及随后通过光电效应进行的检测在这个过程中,光子是彼此独立地被随机地检测到的。被检测到的光子的定时信息被用来生成随机的二进制数字-位。
Andras Vass

Answers:


114

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

例如,Linux上的/ dev / random(4)收集来自硬件中断时序变化信息,这些信息来自硬盘返回数据,按键和传入网络数据包等来源。如果内核不会高估其收集的熵,则此方法是安全的。几年前,来自各种不同来源的熵估计都减少了,使它们变得更加保守。这是Linux如何估计熵解释

以上所有都不是特别高的吞吐量。/ dev / random(4)可能是安全的,但它通过在无法确定数据是安全随机的情况下拒绝提供数据来维护该安全性。例如,如果要生成许多加密密钥和随机数,则可能需要使用硬件随机数生成器。

通常,硬件RNG的设计目的是从一对以接近相同速度运行的振荡器之间的差异中进行采样,但是振荡器的速率会根据热噪声而略有变化。如果我没记错的话,用于英国高级债券彩票的随机数生成器ERNIE就是这样工作的。

替代方案包括对CCD上的噪声(请参阅lavaRND),放射性衰变(请参阅hotbits)或大气噪声(请参阅random.org,或者只是将电台以外的其他地方调谐的AM收音机插入声卡)进行采样。或者,您可以直接要求计算机的用户敲打键盘,就像是一只混乱的黑猩猩,不管漂浮在船上的是什么。

正如安德拉斯(Andras)指出的那样,我只想谈论一些最常见的熵收集方案。托马斯·波宁(Thomas Pornin)的回答约翰内斯·罗塞尔(JohannesRössel)的回答都很好地解释了如何处理聚集的熵以便再次分发它。


13
关于收集熵的好方法。尤其是黑猩猩的东西。+1
安德拉斯·瓦斯

5
好干净的答案。谢谢。“我必须在这个网站上花费更多时间”-大声笑
拜伦·惠特洛克

2
@Chris:由于大多数CSPRNG都是通过对种子应用加密功能来工作的,为什么要降票?约翰尼斯(Johannes)对这个问题给出了很好的答案:如果我有种子,有什么选择?理查德·我相信,在解释如何获得种子方面做得相当不错。因此,如果有的话,您应该反对约翰内斯,因为这两个答案共同提供了答案。另外,请阅读整个问题,而不仅仅是标题。
安德拉斯·瓦斯

3
@克里斯:无论您的(确定性)CSRNG有多好,它永远不会比初始种子好。如果仅将64位熵放入CSRNG中,但提取128位作为AES密钥,则种子就是弱链接,攻击者可以通过强行使用CSRNG来找到您的密钥。
Rasmus Faber

3
专注于晦涩而奇特的熵源弊大于利。正如Thomas Pornin解释的那样,仅需要128位左右。启动后不久便面临主要挑战。在奇特的情况下(例如,服务器的内存映像已泄漏),以后添加更多内容可能会有所帮助,但是减少内部熵估计并阻止输出是旧的建议,在现代CSPRNG设计中无济于事。几个BSD操作系统仅将/ dev / urandom链接到/ dev / random。
Marsh Ray

52

出于加密目的,需要的是流应“在计算上与统一随机比特没有区别”。“以计算方式”意味着它不需要真正地随机,而只是在没有访问上帝自己的计算机的任何人身上都可以看到。

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

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

一旦有了n位,就使用PRNG(伪随机数生成器)来根据需要启动尽可能多的位。如果假定PRNG在足够宽的未知n位密钥上操作,并且其输出在计算上与统一随机位没有区别,则PRNG被认为是密码安全的。在90年代,一个流行的选择是RC4,它实现起来非常简单,而且速度很快。但是,事实证明它具有可测量的偏差,即,它并没有最初希望的那样难以区分。该eSTREAM项目包括收集PRNG的更新设计(实际上是流密码,因为大多数流密码都包含在PRNG中,其输出与要加密的数据进行异或运算),将它们记录下来,并促进密码学家的分析。eSTREAM产品组合包含七个PRNG设计,这些设计被认为足够安全(即,他们抗拒分析,而密码学家往往对为什么抗拒有很好的了解)。其中有四个是“针对软件进行了优化”。好消息是,尽管这些新的PRNG似乎比RC4安全得多,但它们的速度也明显更快(我们在这里谈论的是每秒数百兆字节)。其中三个是“免费使用”,并提供了源代码。

从设计的角度来看,PRNG重用了分组密码的许多元素。使用了雪崩和将位扩散到较宽的内部状态的相同概念。可替代地,一个体面PRNG可以从一个块密码来构建:简单地使用Ñ比特序列作为计数器(表示为一个的钥匙插入一个块密码,和加密连续值比特序列,如果该分块密码术用途中号-位块)。只要块密码是安全的,这将产生一个伪随机的比特流,该比特流在计算上与随机是无法区分的,并且所产生的流不超过m * 2 ^(m / 2)个比特(对于m = 128,这意味着大约3,000亿千兆字节,因此对于大多数用途来说已经足够大了)。这种用法称为计数器模式(CTR)

通常,CTR模式下的分组密码不如专用流密码那么快(流密码的要点是,通过放弃分组密码的灵活性,可以期望获得更好的性能)。但是,如果您碰巧拥有Intel最新的带有AES-NI指令的CPU (基本上是硬件中的AES实现,集成在CPU中),那么采用CTR模式的AES将产生无与伦比的速度(每GB几千兆字节)第二)。


16

首先,密码安全的PRNG的目的不是要生成完全不可预测的序列。正如您所指出的,缺少能够产生(或多或少)大量真实随机性1的事物使得这不可能。

因此,您只能诉诸一些很难预测的事情。“硬”在这里意味着要花费太长的时间,到时无论如何它都变得过时了。有许多数学算法在其中起作用–如果您使用一些著名的CSPRNG并查看它们的工作原理,您可以一窥。

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

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

有时还使用计数器上的哈希函数。维基百科对此有更多的介绍

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

至于初始化,大多数CSPRNG使用系统上可用的各种资源,从真正随机的事物(如线路噪声,中断或系统中的其他事件)到其他事物(如某些内存位置&c)。初始化向量最好是真正随机的,并且不依赖于数学算法。这种初始化在Debian的OpenSSL实现中被破坏了一段时间,这导致了严重的安全问题。


1这也有问题,必须谨慎消除偏差,因为诸如热噪声之类的东西根据温度而具有不同的特性-您几乎总是有偏差并且需要消除偏差。但这本身并不是一件容易的事。


很好的答案。感谢您抽出宝贵的时间来解释。
拜伦·惠特洛克

这也使得一个有趣的阅读别人怎么想出一些时髦的方法来提取一些熵:-):en.wikipedia.org/wiki/...
安德拉斯Vass的

@Byron:可能会有更好的选择。我并不是加密货币专家。
乔伊

6

为了使随机数生成器在密码学上被认为是安全的,需要对已知算法和(大量)先前生成的位的对手的攻击进行安全保护。这意味着具有该信息的人无法重建生成器的任何隐藏内部状态,并且无法以50%以上的准确度预测下一个生成的位。

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

因此,关于它们的工作方式,任何好的加密系统都可以用作加密安全的随机数生成器-使用该加密系统对``正常''随机数生成器的输出进行加密。由于对手无法重建正常随机数生成器的明文输出,因此他无法直接对其进行攻击。这是一个有点循环的定义,这引出了一个问题,即如何加密密码系统以保持其安全,这是另一个问题。


一个很好的解释,谢谢。但是,我认为您的最后一句话是使OP真正出错的原因,他说:“我知道有些仪器可以读取宇宙白噪声以帮助生成安全的哈希,但是您的标准PC却没有。”
安德拉斯·瓦斯

安德拉斯:我完全不认为这是OP的问题,但也许他想澄清他的要求。
克里斯·多德

“准确度高于50%”如果可以以60%的准确度预测下一位,则不再使用它,因为对于大量的位,猜测它们的概率仍会收敛为零,并且蛮力搜索仍然只能改善很小的数量。即使使用99.99%的速率,只要没有办法对其进行改进,它仍可以安全的方式使用(位数增加了数百倍)。普通的RNG甚至足够,因为不可避免地会出现偶然的计算错误,但是生成足够数量的数字在计算上是不可行的。
AJMansfield

@AJMansfield:尽管您始终可以将加密白化应用于非加密安全的RNG以创建加密安全的RNG,但这并不能使原始RNG变得安全,而只是使组合的RNG变得安全。使用加密安全的RNG进行诸如密钥生成之类的事情的意义在于,这意味着对于攻击者来说,要想破解密钥,哪怕只是很小的常数,也没有比蛮力更好的方法了。
克里斯·多德

@ChrisDodd你知道生日袭击是什么吗?几乎每个密码系统都会遭受某种类型的生日攻击,这是标准暴力破解速度的两倍
AJMansfield

5

每个生成器都将使用自己的种子策略,但这是有关CryptGenRandomWindows API文档的一些内容

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

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


哦,很漂亮。方便地知道它在Windows-land中是如何完成的,谢谢。
理查德·巴雷尔
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.