我了解标准随机数生成器的工作原理。但是当使用密码术时,随机数确实必须是随机的。
我知道有些仪器可以读取宇宙白噪声以帮助生成安全的哈希,但是您的标准PC却没有。
密码安全的随机数生成器如何获得没有可重复模式的值?
我了解标准随机数生成器的工作原理。但是当使用密码术时,随机数确实必须是随机的。
我知道有些仪器可以读取宇宙白噪声以帮助生成安全的哈希,但是您的标准PC却没有。
密码安全的随机数生成器如何获得没有可重复模式的值?
Answers:
您可能用来生成加密密钥的加密安全数字随机数生成器通过从其他人无法观察到的来源收集熵(即不可预测的输入)来工作。
例如,Linux上的/ dev / random(4)收集来自硬件中断时序变化信息,这些信息来自硬盘返回数据,按键和传入网络数据包等来源。如果内核不会高估其收集的熵,则此方法是安全的。几年前,来自各种不同来源的熵估计都减少了,使它们变得更加保守。这是Linux如何估计熵的解释。
以上所有都不是特别高的吞吐量。/ dev / random(4)可能是安全的,但它通过在无法确定数据是安全随机的情况下拒绝提供数据来维护该安全性。例如,如果要生成许多加密密钥和随机数,则可能需要使用硬件随机数生成器。
通常,硬件RNG的设计目的是从一对以接近相同速度运行的振荡器之间的差异中进行采样,但是振荡器的速率会根据热噪声而略有变化。如果我没记错的话,用于英国高级债券彩票的随机数生成器ERNIE就是这样工作的。
替代方案包括对CCD上的噪声(请参阅lavaRND),放射性衰变(请参阅hotbits)或大气噪声(请参阅random.org,或者只是将电台以外的其他地方调谐的AM收音机插入声卡)进行采样。或者,您可以直接要求计算机的用户敲打键盘,就像是一只混乱的黑猩猩,不管漂浮在船上的是什么。
正如安德拉斯(Andras)指出的那样,我只想谈论一些最常见的熵收集方案。托马斯·波宁(Thomas Pornin)的回答和约翰内斯·罗塞尔(JohannesRössel)的回答都很好地解释了如何处理聚集的熵以便再次分发它。
出于加密目的,需要的是流应“在计算上与统一随机比特没有区别”。“以计算方式”意味着它不需要真正地随机,而只是在没有访问上帝自己的计算机的任何人身上都可以看到。
实际上,这意味着系统必须首先收集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几千兆字节)第二)。
首先,密码安全的PRNG的目的不是要生成完全不可预测的序列。正如您所指出的,缺少能够产生(或多或少)大量真实随机性1的事物使得这不可能。
因此,您只能诉诸一些很难预测的事情。“硬”在这里意味着要花费太长的时间,到时无论如何它都变得过时了。有许多数学算法在其中起作用–如果您使用一些著名的CSPRNG并查看它们的工作原理,您可以一窥。
构建此类PRNG的最常见变体是:
有时还使用计数器上的哈希函数。维基百科对此有更多的介绍。
一般要求只是从发生器的位流中确定原始初始化向量是不可行的,并且下一位很难轻易预测。
至于初始化,大多数CSPRNG使用系统上可用的各种资源,从真正随机的事物(如线路噪声,中断或系统中的其他事件)到其他事物(如某些内存位置&c)。初始化向量最好是真正随机的,并且不依赖于数学算法。这种初始化在Debian的OpenSSL实现中被破坏了一段时间,这导致了严重的安全问题。
1这也有问题,必须谨慎消除偏差,因为诸如热噪声之类的东西根据温度而具有不同的特性-您几乎总是有偏差并且需要消除偏差。但这本身并不是一件容易的事。
为了使随机数生成器在密码学上被认为是安全的,需要对已知算法和(大量)先前生成的位的对手的攻击进行安全保护。这意味着具有该信息的人无法重建生成器的任何隐藏内部状态,并且无法以50%以上的准确度预测下一个生成的位。
普通的伪随机数生成器通常在密码上是不安全的,因为从先前输出的位中重建内部状态通常是微不足道的(通常,整个内部状态只是直接产生的最后N位)。没有良好统计特性的任何随机数生成器也不是密码安全的,因为即使不知道内部状态,其输出也至少是可预测的。
因此,关于它们的工作方式,任何好的加密系统都可以用作加密安全的随机数生成器-使用该加密系统对``正常''随机数生成器的输出进行加密。由于对手无法重建正常随机数生成器的明文输出,因此他无法直接对其进行攻击。这是一个有点循环的定义,这引出了一个问题,即如何加密密码系统以保持其安全,这是另一个问题。
每个生成器都将使用自己的种子策略,但这是有关CryptGenRandom的Windows 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缓冲区的步骤。