显然,如果您需要一个随机数进行加密,则代码应使用从硬件获取它的api。但是,并非所有硬件都有SRNG可用。如果您正在开发安全性至关重要的应用程序,并且硬件RNG不可用,则适当的操作方法是中止执行。

但是,并不是每个应用程序都被视为对安全性至关重要。也就是说,尽管您需要安全性,但是您不必担心过于复杂的攻击,因为:1.您的应用程序不值得被老练的黑客破解; 2.您的任何数据都不被视为严格机密(您不会希望它被破坏了,但那不会是世界末日。)

假设一个非安全关键应用程序在没有硬件RNG或ECC内存的计算机上运行,​​那么分配一个非常重要的应用程序是否可行大量的内存(可能是一个长循环),并使用最终发生的错误作为随机性的来源?这样会比PRNG安全吗?

评论

我的假设是,如果您的内存经常发生错误,足以使它成为可用的熵源,那么,您可能会遇到无法可靠运行任何程序的问题…… ,并且等一会儿,存储电容部分放电,这是以前提出的;不太受欢迎(IIRC)...

@poncho好,您将必须执行类似的操作,例如,分配2GB的内存并检查其错误100000次,或者执行类似的操作。

您对“非安全性至关重要”的定义是什么?根据我对该术语的定义,/ dev / urandom足以满足非安全性至关重要的数字的99.9999%。

将应用程序定义为非安全性至关重要的问题是,您无法预测人们将如何使用该应用程序以及他们将如何信任该应用程序。这就是为什么即使有些开发人员认为HTTPS的应用程序不需要HTTPS仍被普遍采用的原因。我确实认为这是一个值得探讨的问题,对于安全性至关重要的应用程序,您是否可以从内存错误中获得高质量的熵,但是我不喜欢说RNG这样的基本功能对于某些安全应用程序来说“足够好”,而不是这样。其他。

@TheCatWhisperer,我上周在一台新建计算机上进行了RAM测试。 24小时的内存测试运行相当于您检查2GB的错误100,000次,却一无所获。

#1 楼

否。

正确运行的计算机在地面上的内存错误率非常低;每周检测到一个错误以上的错误(由带有ECC日志记录的计算机报告)是维护的原因[#]。因此,所提出的方法需要终端上不切实际的延迟来获得任何熵,或者计算机不可靠。对于一口井来说,这主要发生在海拔高度(尤其是在南大西洋异常地区)。另外,如果机器具有ECC,则很难检测到错误(报告ECC错误往往是专有的混乱);如果不是这样,并且有相当多的错误,那是担心一个人最终会阻止程序按预期运行。
音频或视频输入;更通常是ADC的输出。
相对于CPU时钟高精度测量的事件时间(例如,通过RDTSC指令或API获得的性能计数器)。来源包括:


按键(值赋予额外的熵)
鼠标/指针设备的移动(位置赋予额外的熵)
网络数据包的到达
具有旋转晶体的硬盘中的数据的可用性
具有独立晶体的实时时钟IC中的秒变化(熵率低,但熵非常可靠)



提取熵相对容易:本质上,对可以得到的任何熵进行哈希处理。一件非常困难的事情是要确定一个可靠的下界,即实际上收集了多少熵。要非常保守,不要以为拥有的东西会。事情出乎意料地发生了变化,尤其是当有积极的对手时,就像我们在加密货币中所假设的那样。[#]关于DRAM的可靠性研究给出了各种各样的估计。但是,我们说的是100FIT par DRAM IC,其系数是100,其中``时间故障''是每109个设备·小时的预期故障数。以最高端104 FIT为例,一台具有4个DIMM且每个均带有18个DRAM IC的计算机(到2017年末,足够使用DDR4主流使用DDR4主流的32 GiB ECC)。服务器的现场经验是,当出现ECC警报的次数多于每周一次时,这是有原因的,通常是内存规格或设置(仅适用于新机器)或特定DIMM的特定IC中的特定位不匹配。边缘(或磨损,对于已经安静哼唱了一段时间的机器)。错误日志的主要优点是可以帮助您识别这种情况,而不是报废整个DIMM,而不是报废整个DIMM。包括将刷新率降低到远低于制造商的规格,和/或使用RowHammer读/写模式。但是,这完全取决于DRAM模型。在操作系统内可靠,便携地执行此操作非常困难; MemTest想要拥有尽可能多的机器是有原因的。

评论


$ \ begingroup $
当音频与任何事物断开连接时,我支持使用音频输入的想法。断开的音频输入会在相当低的水平上吸收很多噪声-将输入切换为“麦克风”而非“线路输入”模式以激活内置前置放大器,您将获得有用的电子噪声源基于电噪声的原理,这可能与任何HRNG一样随机。请注意,尽管攻击者当然可以录制与您相同的音频输入,从而可以访问相同的随机数据。
$ \ endgroup $
–米歇尔·约翰逊(Micheal Johnson)
17年11月8日在7:50

$ \ begingroup $
@Simone不,你误会了。我不建议使用麦克风来记录声音,我建议使用断开的麦克风输入作为电噪声源(断开的输入始终会产生噪声,并且该噪声会被内部前置放大器放大) 。具有与目标应用程序相同的计算机上运行的恶意软件的攻击者可以录制与目标应用程序相同的音频输入,从而可以访问相同的噪声源。
$ \ endgroup $
–米歇尔·约翰逊(Micheal Johnson)
17年11月8日在8:35

$ \ begingroup $
@Simone我想象一些硬件随机数生成器将隔离不同应用程序之间的访问。因此,硬件随机数生成器的值总是在变化,因此两个应用程序永远无法查询并获得完全相同的值,因为它们在不同的时间点进行查询。音频输入总是记录在一个缓冲区(但是很小)中,如果同时记录多个应用程序,则很容易在一个时间点捕获相同的数据,然后将其放置到多个缓冲区中。
$ \ endgroup $
–米歇尔·约翰逊(Micheal Johnson)
17年11月8日在8:49

$ \ begingroup $
@TheCatWhisperer:嗯,我最常使用的服务器没有音频输入。他们确实有英特尔的RDRAND。
$ \ endgroup $
–fgrieu♦
17年11月8日在14:11

$ \ begingroup $
@Simone使用RNG时,通常不清楚如何使用这些数字。实际上,这是RNG的主要设计因素。您不知道噪声的哪些方面在最终使用中将很重要。因此,目标是最大程度地降低任何人能够模拟流的可能性,并且通常这样做的程度要远远超过真正需要的熵水平,以防万一事实证明您的熵估算器很远。安全胜过遗憾。
$ \ endgroup $
–Cort Ammon
17年11月8日在15:56

#2 楼

很难想象您可以为您的系统提供大量的RAM,但是却无法负担硬件RNG,例如便宜的模型(价格为0.25美元,或降低到0.01美元,但要付出一些人机工程学费用),在国际上可以买到。其他国家也有。您甚至可能口袋里只有一个。

但是,假设您使用的是ECC RAM,它向操作系统报告错误事件的数量,从而可以轻松地从操作系统中查询。考虑一下以泊松分布的错误事件计数,其速率为每周一次,如@fgrieu建议将其作为速率上限,然后再将其全部清除并购买新的RAM。从一周的错误计数中得出的熵是多少?以比率$ \ lambda $计数$ k $的概率为$$ \ operatorname {泊松}(k; \ lambda)= \ frac {\ lambda ^ ke ^ {-\ lambda}} {k!}。$$泊松分布变量的熵没有很好的封闭形式表达式,但是我们可以使用$$ \ lambda \ cdot(1-\ log \ lambda)+ e ^ {-\ lambda} + sum_ {k = 0} ^ \ infty \ frac {\ lambda ^ k \ log k!} {k!}。$$如果我们修复$ \ lambda = 1 $,这意味着我们测量一周,则简化为$$ 1-\ log 1 + e ^ {-1} \ sum_ {k = 0} ^ \ infty \ frac {\ log k!} {k!} \ approx 1.3 \; \ mathrm {nat} \ approx 1.9 \; \ mathrm {bit} $ $,如果我正确地进行了计算。

也就是说,通过等待大约一周左右的时间来旋转手指,您会得到不到一点点的熵-拇指的本来可以在短得多的时间内翻转硬币时间更大的熵。那就是香农熵,而不是密码学家所使用的最小熵!最小熵恰好是$ 1 \; \ mathrm {nat} \ approx 1.4 \; \ mathrm {bit} $。

读者的练习:假设您可以某种时钟分辨率(例如,天,小时,分钟,秒)来测量到达间隔的时间,而不是最后的计数—可能是事件发生硬件中断,或者每分钟/秒/等轮询一次。那时候的(Shannon,min-)熵是多少?

评论


$ \ begingroup $
你不会从错误发生的地方得到熵吗?假设它是均匀分布的,您将获得32位(假设您具有4 GiB的RAM)-远远超过定时。
$ \ endgroup $
– Maciej Piechotka
17年11月8日在4:14

$ \ begingroup $
@MaciejPiechotka对-您可以通过合并有关错误发生时间的信息来进一步改善这一点。如果您不断检查错误,那么没有理由不应该将其固定到第二个(DDR4-2400可以管理76 GB / s的吞吐量,远远超出您的需求),因此大约19位左右,具体取决于您将其推入多远。
$ \ endgroup $
–查尔斯
17年11月8日在7:32

$ \ begingroup $
平心而论,我应该提到不断擦洗高速RAM的能源成本将远远超过硬件RNG的成本。
$ \ endgroup $
–查尔斯
17年11月8日在7:33

$ \ begingroup $
@Charles鉴于rdrandr的存在,其成本可能为0。关键是它的运行速度非常慢(位数/周)。
$ \ endgroup $
– Maciej Piechotka
17年11月8日17:41



$ \ begingroup $
@MaciejPiechotka是的,如果添加时间信息,它仍然很慢。
$ \ endgroup $
–查尔斯
17年11月8日在17:55

#3 楼

我假设您实际上是指内存错误,而不是初始开机状态。

它无法正常运行。没有内存错误。我再说一遍,没有内存错误。现代RAM相当不错。就像微处理器一样,它要么起作用要么不起作用。我已经运行MemTest86了很多次。我发现了三种情况:



整夜运行后内存通过失败为零。取出存储卡,用砂纸+螺丝刀擦拭/打磨连接器或锉刀,然后重新测试。接触氧化是PITA。几乎每次都变为1。
内存失败,并带有错误提示。夹住切屑并/或获得退款。

情形3很少发生。这就是为什么大多数计算机(从统计上来说)运行非ECC芯片的原因。另外,英特尔不允许使用消费者ECC,并且大多数台式机都可以正常运行。您的手机,笔记本电脑或平板电脑也没有。而且他们大部分时间都在工作,不是吗?我的非ECC服务器的正常运行时间超过365天。我认为漫长的循环不会找到任何结果。因此,作为竞争策略,这使得AMD对ECC的支持颇有疑问。

下图是标题为“现代系统中的内存错误”的论文的摘录。它只是众多论文中的只有一篇,因此,您将可以使用它:-



总而言之,该图显示了大型计算机的每月错误率。您可以看到每个DRAM芯片的错误率很小。一天之内,他们每个月最多可获得30个FIT /芯片,但是这种速度会随着时间而降低。单个FIT是指单个设备运行10亿小时后发生的单个故障。每天不是30次失败。因此,这仅在他们分析的十亿磅级机器中真正重要。如手机所示。

结果是您不能将错误作为熵源,因为没有任何统计上显着的数量。而且,如果确实找到了某些错误,那就是错误,并且不能依靠它,因此您无法发布代码以将其用于熵提炼。您将不会指出哪台机器有错误或有多少错误。从“重新审视大型生产数据中心中的内存错误:现场新趋势的分析和建模”看来,很难确定一台适合于DRAM熵提取的机器。他们研究了整个Facebook服务器产业超过一年。他们的发现表明:-错误非常集中在特定的个人计算机上。 1%的服务器负责97.8%的错误。修复那些服务器,您几乎没有熵。因此,从另一方面来说,您随机指向的服务器几乎不会产生任何错误的概率为99%。
这取决于计算机的具体工作。工作负载类型最多可影响服务器故障率6.5倍。
错误的大多数(未指定百分比)实际上是由内存控制器而不是DRAM单元引起的。
假设的最终结果是良好的的观点是,错误率与单元和CPU密度之间存在明显的相关性。我们都可以期待将来可靠性会大大降低(并且熵会更多)。

最后,作为练习,您将如何使用内存错误?这是不可能的。 MemTest可以找到它们,因为它是仅在计算机上运行的微型应用程序。遇到随机定位的错误不会使MemTest崩溃。我想错误可能发生在它的程序空间内,但是您永远不会知道它会崩溃而不会报告它。在具有虚拟机和大量IO的多任务操作系统上,如果发生重大错误,整个过程可能会崩溃。我认为您可能不会出现仅在内存映射的方便且可访问区域发生内存错误的情况。

有更好的方法从计算机获取熵。

评论


$ \ begingroup $
我记得读过一些地方,如果您通过总线从硬盘驱动器传输足够的数据,这些东西的容量大约为TB,那么您将出错,这将使处理超大文件变得困难。
$ \ endgroup $
–TheCatWhisperer
17年11月8日13:53

$ \ begingroup $
@TheCatWhisperer:您不会仅仅因为对数据(甚至是TB级)进行混洗而得到错误。 (如果是这样,仅备份大量数据几乎是不可能的。)只是,如果您已经拥有不稳定的硬件,则长时间的辛苦工作会增加其崩溃的可能性。
$ \ endgroup $
– cHao
17年11月8日在16:19

$ \ begingroup $
@cHao:文件系统开发人员(尤其是ZFS的校验和数据)确实表示清理磁盘很有用。 blogs.oracle.com/7000tips/disk-scrub-why-and-when。我真的不确定在未损坏的台式机中是否存在未通过SATA和内存总线检测到的错误,或者这主要是为了在损坏所有文件之前从脆弱的硬件中及早发现数据损坏。
$ \ endgroup $
– Peter Cordes
17年11月8日在18:40

$ \ begingroup $
@cHao:另:en.wikipedia.org/wiki/…说,在一年中,任何给定的计算机都会遭受内存错误的可能性约为1/3。如果它不使用ECC内存,那将是一个真正的错误。复制TB数据仅需数小时或数天,而无需一年,因此,我同意通常可以安全地复制数据。不过,存储校验和(甚至是少量的par2前向纠错数据)也不是坏主意。
$ \ endgroup $
– Peter Cordes
17年11月8日在18:49



$ \ begingroup $
@Peter:别误解:Wikipedia是次要来源。它说,一项研究声称,一年之内,雅达·雅达。其他研究给出了不同的结果。它还说,许多研究报告说,大多数错误是“硬”错误(即:由于片状硬件而不是宇宙射线所致)。
$ \ endgroup $
– cHao
17年11月8日在19:22

#4 楼



其他答案详细介绍了这个问题。

但是至少有一篇文章讨论了使用RFID芯片的SRAM存储器内容的想法。上电后获得设备的指纹和一些随机位。

总结是SRAM单元是6个晶体管的对称结构,在两种配置之一中亚稳态, 01。上电时,SRAM单元的两侧争夺主导地位。哪一个获胜取决于晶体管之间的微小内在差异以及噪声。这些可以用来导出指纹。在其他单元格中,这些差异是如此之小,以至于噪声占主导地位,并且这些单元格可能会以任一值加电。这些可以用来获取一些熵。

这是从纸上得到的图像。在左侧,以图表形式绘制了0 / 1偏斜。右边是存储区域的可视化表示。黑格是可靠地初始化为0的位;白细胞可靠地初始化为1;灰色单元格可能会初始化为以下两种状态:



本文是“初始SRAM状态作为指纹”和“ RFID标签的真实随机数”的来源Daniel E. Holcomb,Wayne P. Burleson和Kevin Fu。 。由于其对称结构,它也以SRAM为目标。我不确定该技术是否可以推广到DRAM或其他内存类型,但是许多计算设备在某些地方可能会使用SRAM(例如:处理器缓存)。

评论


$ \ begingroup $
DRAM通过将位存储在电容器中来工作。这些随着时间流逝。换句话说,这些位自然复位。这就是为什么DRAM需要定期刷新的原因。如果硬件访问量不足,则可以暂停刷新并确定哪些位重置最快。
$ \ endgroup $
– MSalters
17年9月9日在12:52

#5 楼

已经指出,存储器错误太少而无用。但是,还有另一个问题-由于芯片中的缺陷(而不是处于宇宙射线的路径中)导致的内存错误不是很随机。它们是某处数据泄漏的结果。您的密钥将显示出非常非随机的分布,并且攻击它的任何人都可能会知道这一点,并确定优先使用哪个密钥的优先级。或摆动鼠标。

评论


$ \ begingroup $
我认为这不是问题。显然,您可以使用哈希或类似方法使熵变白。
$ \ endgroup $
–马丁·邦纳(Martin Bonner)支持莫妮卡(Monica)
17年11月8日在10:21

$ \ begingroup $
@MartinBonner实际上,这是一个很大的问题,具体取决于如何使用该错误。例如,如果使用了错误的位置(如另一个答案中所建议的),而实际错误仅发生在某些特定位置,那么实际的熵要比估计的低很多,并且哈希不能增加熵(没有确定性算法即可)。
$ \ endgroup $
– tylo
17年11月8日在12:22

#6 楼

不,正如已经指出的那样,等待内存错误不是一个好主意。首先,您将非常依赖于特定的内存类型。如果有人用错误检查和纠正(ECC)内存替换内存,那么您将已经遇到问题。内存错误的数量将最小化,或者在现代计算机上不存在,并且分配/扫描整个内存将占用大量CPU和内存带宽。内存错误的数量也可能对环境敏感。例如,攻击者可以降低温度,以尝试最大程度地减少由内存错误产生的熵。

有时执行的操作是分配内存并在不清除内存的情况下将其读出,并回读所有可能存在于此类内存中。这必须是一种操作系统功能,因为操作系统可以很好地擦除内存本身。通常,这样做仅是为了向RNG添加一点熵,而不是将其作为主要来源。此外,事实证明这很危险:当静态代码分析工具发现未初始化内存的读取并且开发人员删除了这种熵源时,Debian和Ubuntu Linux发行版立即受到影响-不幸的是,包括所有其他熵源。 >

如果没有良好的True Random Generator,使用较小的时序差异(如果有一个好的计时器,则以纳秒为单位)似乎是收集熵的最佳方法之一。它仍然存在一些问题,例如在无头环境或VM中运行。显然,随着SSD逐渐成为主流,使用HDD的随机源特性已经不再是一个好主意了。

评论


$ \ begingroup $
您真的可以在DRAM上获得ns时序信息吗?我不知道如何真正到达控制器外部的DRAM计时器。当我们制造IC时,我们可以使用它们,因为我们需要将坏的DRAM块上的行炸掉。但是,我不知道有人迟到闩锁。您对此有很好的参考吗?
$ \ endgroup $
–b degnan
17年7月7日在23:22

$ \ begingroup $
@bdegnan:我相信这个主意是看一下CPU上的周期计数器。也就是说,DRAM响应需要多长时间的微小差异将显示为CPU周期数的增量...
$ \ endgroup $
–雨披
17年7月7日23:39

$ \ begingroup $
我认为您对“未初始化的内存读取”的解释是错误的。我记得它的风险是编译器发现了未初始化的内存读取,并将其传播到RNG状态本身。从优化程序的角度来看,存在问题<未初始化> XOR 1 = <未初始化>,因此可以安全地删除XOR。
$ \ endgroup $
– MSalters
17年9月9日13:20

#7 楼

我不确定内存错误,但是我确实使用未知的并行计算执行顺序成功编写了一种改组算法。
通过同时传递每张卡,我会将卡(int)从一个卡片组(列表)移动到另一个卡片组(列表)到不同的线程并让所有线程“竞争”以将它们重新插入到另一个平台中。
不断重复执行几秒钟后,该平台似乎完全被洗净了,即使我当时不曾两次获得相同的结果运行相同的代码。即使在同一台计算机和相同的环境中也是如此。但是我猜想它在很大程度上取决于它执行的环境是否足够随机。

评论


$ \ begingroup $
我将非常关心将其用于熵...正在调度线程的OS仍是确定性的。我怀疑这种技术产生的熵会很低
$ \ endgroup $
–TheCatWhisperer
17年11月9日在14:33

$ \ begingroup $
@TheCatWhisperer我不太确定。我一直在玩同样的东西。尽管指令到指令步骤是确定性的,但鉴于数十亿次操作和分支与中断,在宏观范围内仍存在一定程度的不可预测的混乱行为。 Java的SecureRandom在必要时使用此方法进行自我播种。可能是可用的熵。
$ \ endgroup $
–Paul Uszak
17年9月9日在21:38