在我看来,生成随机数的硬件组件非常简单-只需用传感器测量硬件中的微小振动,对吗?也许我是错的,但是如果您以很高的精度测量振动,则很容易生成无法猜测的随机数。

但是,我是密码学新手,并且了解甚少。因此,我正在阅读,并且有一篇文章说:


,您只是不需要那么复杂就能削弱随机数生成器。这些发电机已经非常脆弱,很难检测何时损坏。 Debian的维护者早在2008年就指出了这一点,当时错误的代码清除将OpenSSL的有效熵减少到只有16位。实际上,RNG非常脆弱,因此这里的挑战不是削弱RNG-任何使用键盘的白痴都可以做到这一点-这样做是在不使实现对其他所有人都非常脆弱的情况下进行的。 >我肯定会缺少一些有关随机数生成如何“脆弱”的关键细节。有人可以解释吗?

评论

实际上,振动在数学上可能实际上比您想象的要一致。我见过一个简单的硬件生成器完成的一种方法是对晶体管进行反向偏置,从而产生量子级随机性。这只是一条简单的Arduino电路...我敢肯定,真正的硬件随机软件包会更加完善。但是并非所有系统都具有可用的硬件...尤其是在虚拟化系统中。

还应该注意的是,您在本文中引用的部分是关于在软件随机数生成器中发现的弱点。

@johndoe当我的电话打开HTTPS网站时,我的电话和服务器都需要生成秘密的随机数。欢迎使用密码学!这是一个广阔的领域,但首先要从一个您了解的角落开始,然后从那里开始积累知识。我发现在该站点上阅读和回答问题对我的学习非常有帮助。

我读这句话的时候是不是加密专家的人,它发出一般警告:“除非您知道自己在做什么,不要修改密码,即使那样,也要非常小心。”在这方面,我认为RNG并不特殊。如果人们开始对他们不了解的代码进行更改,那么任何加密代码都将变得脆弱。

应当指出,Debian RNG的失败与加密本身的脆弱性无关,这主要是由于在某些语言中引入无声错误(例如调用未定义的行为)有多么容易。

#1 楼

硬件与软件RNG
您提到的第一件事是硬件噪声源。某些亚稳态现象的高精度测量足以生成不可预测的数据。这可以通过使用反向偏置的齐纳二极管,环形振荡器,ADC甚至是盖革计数器来完成。甚至可以通过测量按键之间的时间间隔的纳秒级延迟来完成。如果硬件本身开始出现故障,则这些噪声源可能会发生故障。例如,如果未将晶体管专门设计为在高电压下反向运行,则晶体管可能会击穿。虽然这些技术具有不同程度的脆弱性,但您引用的文本中并未讨论这些技术。
您提到的第二种RNG是称为伪随机数生成器(PRNG *)的软件RNG。这是一种算法,它获取类似于加密密钥的种子,并将其扩展为无限的数据流。它试图确保在不知道算法开始的秘密随机种子的情况下,除了纯随机性之外,无法预测或告知数据。在这种情况下,PRNG是用纯软件实现的,因此打破它仅需在代码中引入错误,这就是您引用的文本所谈论的内容。仅仅是代码易碎,如果对代码进行更改会偏离算法预期的行为,则可能会导致完全失败。实际上,您可以通过使用诸如AES之类的密码来加密计数器来创建加密安全的PRNG。只要加密密钥(种子)是秘密的,就无法预测输出并且无法发现种子。当您以这种方式考虑时,将变得更容易理解,代码中的小而无关紧要的更改会完全破坏算法的安全性。
收集随机性那么现代设备实际上如何收集随机性呢?让我们以一个服务器在数据中心中的某个地方安静地运行。为了支持TLS,它需要大量完全不可预测的数据,这些数据无法与真正的随机流区分开。如果没有专用的硬件噪声源,则随机性必须来自内部。计算机努力做到完全确定性,但它们从非确定性设备中获得了大量输入。 Enter ...中断!
在现代硬件中,中断是硬件发出的信号,用于警告CPU状态更改。它允许CPU避免快速轮询每个硬件设备以获取更新,而是相信该设备将在时间到来时异步警告它。发生中断时,将调用中断处理程序来处理信号。事实证明,此处理程序是获得随机性的理想场所!当测量中断的纳秒级时序时,您可以快速获得相当大的随机性。这是因为,从到达NIC的数据包到从硬盘驱动器读取数据的各种事件都会触发中断。这些中断源中的一些中断源是不确定性的,例如依赖于执行器物理运动的硬盘驱动器。
一旦操作系统收集到足够的随机位,则至少可以包含128位的小种子被馈送到加密安全的PRNG中以生成无限量的伪随机数据流。除非有人能够准确地预测每个过去的中断发生的时间(精确到纳秒级),否则他们将无法获得种子,也无法预测未来的PRNG输出。这使得输出完全适合TLS密钥。
*面向安全的PRNG称为加密安全PRNG或CSPRNG。当应用程序要求CSPRNG时使用常规PRNG可能会导致安全漏洞。

评论


齐纳二极管不是专门为反向工作而设计的吗?

– Hymomo
18年7月29日在8:26

它是齐纳二极管,而不是齐纳二极管-以Clarence Zener命名。

–俄罗斯
18年7月29日在12:56

我认为您应该删除关于“未专门设计为在高压下反向运行”的句子。所谓的“齐纳二极管”可以使用齐纳或雪崩效应,也可以同时使用两者,当然,它们被设计为在反向击穿时无限期工作。也许您有主意,因为晶体管E-B结有时用于反向击穿,而并非设计用于这种方式。

– Spehro Pefhany
18年7月30日在14:51



我喜欢这个答案,除了它甚至没有提到PRNG与CSPRNG。实际上,只有一种尝试是不可预测的。另一个只是试图让您获得很多数字,这些数字乍一看似乎是无关的。 (不是按此顺序。)这是一个重要的区别,尤其是在此站点上。在您打算使用CSPRNG的地方使用PRNG可能会导致严重的问题,而反向则可能会损失很多性能(这也会引起问题)

–莫妮卡基金的诉讼
18年7月30日在18:07



@NicHartley我添加了一个脚注来说明区别。谢谢!

–森林
18年8月2日,0:03

#2 楼

从历史上看,适用于密码学的硬件RNG在PC上并不普遍可用:例如,根据这个问题,AMD几年前才增加了支持,所以即使到了今天,软件供应商也不能简单地假设它会可用。这大概就是为什么OpenSSL(如您的报价中所述)使用软件RNG的原因,使其容易受到代码中发现的错误的影响。

(正如评论中广泛讨论的那样,标准PC确实包含许多RNG软件可以利用的“熵源”-我相信OpenSSL可以,尽管我并不十分担心熟悉它-但显然在那种情况下,软件错误可能会导致错误的随机数,确实确实发生了。)具有其他熵源的硬件RNG,而不是照原样使用它们。 (在您的链接文章中还提到了后门硬件,与您引用的内容相比,有几段内容。)问题表明……一方面,幼稚的实现可能容易受到各种物理攻击,例如,如果您基于振动生成随机位,那么如果有人对它进行超声检查会怎样?即使在理想条件下,结果中也可能存在某种偏差,可能会使生成的位对于加密使用而言是不安全的。但是到那时,您又回到了一个问题,即算法(或其实现)是否被故意破坏了,或者是否没有想象中的那么健壮。

评论


实际上,硬件RNG可用了很长时间。您对任何类型的硬件RNG的CPU随机性指令都感到困惑。甚至第一代视频控制台也使用了所谓的硬件RNG。

–森林
18年7月29日在3:22



@HarryJohnston:大多数PC都有很好的随机性来源。将声卡的模拟增益设为最大,会产生热噪声。将网络摄像头的模拟增益设为最大,会产生热噪声。测量用户输入中的变化,会产生噪音。测量湍流引起的HDD旋转速度波动,您会得到噪音。测量主板上的电压波动,您会得到噪音。举例来说,您可以google / bing获取LavaRand。直到最近您还没有在CPU中内置硬件RNG,并带有相应的标准化指令。

–Jörg W Mittag
18年7月29日在9:17

@JörgWMittag,大多数系统没有该硬件。机架中的服务器根本没有声卡,网络摄像头或用户输入设备,并且大多数较新的服务器都具有SSD而不是HDD。而且它们没有高精度的测量设备。解决方案需要应用于各种机器,而不仅仅是传统的台式机或笔记本电脑。

–约翰·迪特斯
18年7月29日在14:37

@JörgWMittag,OP并未询问“随机性来源”。

–哈里·约翰斯顿(Harry Johnston)
18年7月29日在19:16

@JohnDeters嗯,在何处获得一些随机性的另一个显而易见的选择是测量网络接口上到达数据包的时间。 (在繁忙的服务器上,这可能比在家用PC上更好。)服务器通常具有相当多的温度传感器。那里的小变化可以提供一些随机性。与电压传感器相同。 SSD可能不会遭受湍流引起的变化的影响,但是I / O时序在纳秒级上仍然不能完全确定。甚至每秒仅收集一次良好的随机性,就可以在两分钟内为您提供可靠的随机种子。

–用户
18年7月30日在5:54

#3 楼

因为它们很难测试

虽然很容易测试随机数生成器以正确的格式生成输出,但是确定它在统计上是否是随机的要涉及得多,并且不太可能包含在自动化测试套件中。如果您破坏了其他许多代码,它们将变得更加明显。

加密必须正确。

通常,很难确保代码正确。许多代码的一个好处是,只有一小部分的正确性错误会导致安全漏洞。但是,使用密码(包括随机数生成器)时,许多正确性错误都将导致漏洞。加密代码必须正确,安全并且很难确保其正确性。要使它变得不安全,需要维护人员进行重大故障。仅剔除仅产生粗略检查而不会产生任何警告的警告的行,这是次充好。

编辑:这不仅是维护者的错,请参阅Angel的评论

评论


好吧,Debian维护者确实在openssl邮件列表上询问,并指出“该池可能接收的熵更少”,并且基本上被告知“删除它们”。

–Ángel
18年7月31日在21:41

@Ángel-感谢您让我知道这一点,它极大地推动了责任。

–paj28
18年8月1日在8:55

#4 楼

任何随机数生成器最重要的方面之一是,每个随机数的值不仅必须完全独立于其生成的所有其他位的值,而且还必须完全独立于对手可能产生的宇宙中的所有其他事物观察或影响。不幸的是,该财产通常是最难保证的财产之一。通常,最好的办法就是以一种与宇宙中任何其他事物都没有任何可利用关系的方式来生成位。有能力影响您的随机数生成器,以便他选择的某些样本将产生95%的概率,而其余样本只有5%的概率。如果只是从这种生成器中读取128位并将其构建为128位密钥,那么将暴力攻击重点放在接近于会影响生成器的位模式的攻击者的攻击者将更有可能如果发电机没有偏见,则可以快速获得成功。但是,假设不是一次选择一位,而是一次选择了一组7位并将它们异或在一起。这样做将使生成128位密钥的时间增加七倍,但是攻击者的影响力将从95/5降低到74/26,大大降低了密钥最终接近攻击者所使用的位模式的可能性试图强行。

另一种选择是,假设要生成128个随机位,以某种方式对它们进行哈希处理,然后再将它们与另外128个随机位进行异或。这将只需要生成256位而不是896位,但是对于攻击者来说,很难利用生成器中的任何偏差。即使枚举最可能的95,000,000,000位128位模式将有大约50%的机会匹配散列之前使用的一组128位,或将散列值进行异或运算的128位,这是异或后的最终分布不会有任何可利用的偏见或信息泄漏。

#5 楼

Linux的/ dev / random,ChaCha20或RdRand等常用的安全RNG在许多常规情况下都能很好地工作。但是,它们远非傻瓜式的。假设您做一些有趣的事情,例如在启动时生成随机数时无法设置您的实时时钟。如果您不了解这会对您的RNG产生怎样的影响,那么确实有人会带走您的私钥。这里几乎没有错误的余地,因为少量的非随机性会损害整个密码协议,例如密钥生成。

尽管天真的摇篮式实现自己的随机数生成器的问题或硬件中的物理干扰引起了很好的讨论,但是随机数生成器在新闻中的大多数漏洞,例如您提到的Debian问题,不是由于这些问题。我反复看到的最大问题是开发人员认为,他们实际上有一个很好的熵来源,可以为随机数生成器提供种子,错误地允许发现和利用随机生成器的状态,或者缺乏严格的测试随机数生成器本身。如果您是使用低熵密钥的TLS客户端的0.75%之一,则NSA不需要后门生成密钥。总而言之,开发人员会忽略少量警告(如果有的话),并假定其RNG在任何应用程序中都可以使用。程序在给定相同输入的情况下会产生相同的输出,因此它们必须从操作系统或硬件中的熵(或不可预测的数据)源中读取。如今,我们有了诸如RdRand命令之类的东西,它每秒可以生成数十或数百MB的熵。但是,具有硬件随机数生成器的设备(例如1951年的Ferranti Mark 1或1999年的Intel 82802 Firmware Hub)是例外,而不是在2010年之前成为规则。

因此,从历史上看,随机数生成器依赖于相对较慢的熵源,例如人为输入或计算机计时,而传统系统可能几乎没有内置的函数,并且具有良好的熵源。例如,Linux的/ dev / random可能使用启动时钟时间,人工输入设备的时序,磁盘时序,IRQ时序,甚至使用其他线程对熵池进行修改。
生成器很脆弱,因为这些获取熵的标准方法不是万无一失的。使这些熵源可预测或受限制的任何因素都会损害您的RNG,例如:


您提到的Debian错误仅将Process ID用于熵。
如果您使用无头的,预先配置的操作系统,该操作系统在引导时生成密钥,那么很多Linux的熵源都是可以预测的。来源

发现Android的Java密码体系结构需要从某些设备上的良好熵源进行显式初始化。
在Linux中过快地生成随机数将使熵池耗尽,速度快于其可补充的程度,从而导致随机数更少。
通常,RNG不会像/ dev / random这样的每个函数调用都获得新的熵。有时您不能足够快地获得足够的熵,或者您不完全相信熵源。因此,取而代之的是将RNG注入已知的熵源,然后从该种子中产生独立的值。但是,当有人弄清楚发生器的内部状态时,情况就会变差,从而导致从克隆智能卡到在拉斯维加斯欺骗作弊机等一切事情。缓冲区溢出攻击或类似攻击可以揭示随机数生成器的状态。利用暴力攻击也可以了解状态,尤其是在已知算法且算法可逆,可以快速计算出已知明文的情况下。 Windows XP,Dropbear SSH库,Chrome中的XorShift128 +以及Messernetwist算法等问题就是这种情况。

要求对这些已知状态的攻击采取高级缓解措施,才能使RNG脆弱。缓解已知状态攻击的最佳方法是不使用易受攻击的算法(如大多数CSRNG)。这个问题也更详细地解释了什么才是好的RNG安全的原因。但是,即使CSRNG有时也有缺点(例如,Linux 2.6.10内核中的RNG漏洞)。因此,深度防御需要缓解措施,例如为随机数生成器使用单独的状态(每个用户可能一个),频繁刷新种子,并通过防止旁通道攻击和缓冲区溢出的保护措施。

责怪开发人员和用户之间

这些RNG通常是脆弱的,因为无法设计防呆系统的库开发人员或OS创建者之间的限制沟通不畅谁期望一个。例如,Linux迫使用户在高延迟/ dev / random和低熵/ dev / urandom之间进行选择。再举一个例子,5.3之前的PHP通过mcrypt_create_iv()之类的接口不支持Windows中的强PRNG,而7.0之前的PHP则没有内置的CSPRNG。

检测困难

在讨论随机数时,有一个流行的讨论要点,对于真正的随机数,每种可能性都是同等可能的,并且有无限数量的潜在模式。那么,您如何真正看待序列并说它不是随机的呢? (相关的迪尔伯特)

实际上,自从M.G. Kendall和B.Babington-Smith在1938年发表的论文。您可以证明特定类型的模式出现的可能性远没有随机机会大。例如,我可以检查数字1是否比其他数字更通用,并且阈值由卡方检验确定。只要这些经过测试的模式至少在远处是可能的,并且您检查了足够长的一组生成的数字,则误报的几率就很小。虽然某些随机数生成器的一些隐藏问题可能会在几年后被发现,但是如果您已经完成了基本的密码分析,然后按照本问题所述进行了工业级测试,那么您就不会做错什么。 >但是,设计人员可能也只是低估了攻击者(您应该如何预测人们会对您的老虎机进行逆向工程和计时?)更糟糕的是,有时专家不会检查随机数生成器或熵的生成,而仅检查RNG使用的结果,例如使用恒定的“随机”输出对PS3固件签名进行签名时。

归根结底,这里的问题与大多数网络安全中的问题相似:您拥有非常复杂的协议,要求和用于随机数的设备。与往常一样,如果您不了解复杂性,那么容易受到攻击者的攻击。

评论


为什么设置RTC不会以任何方式影响随机性?

–森林
19-3-22在2:57



@forest RTC用于Linux熵池,因此,如果RNG在可预测的时间使用(例如,在引导时生成密钥),则可以导致更可预测的密钥。我将编辑答案以进行澄清。有关更多信息,请参见本文:factorable.net/weakkeys12.extended.pdf

– Cody P
19-3-22在5:33



那不是RTC,而是TSC(通过RDTSC指令的参考周期计数器,尽管我相信某些MIPS32系统使用不同的计数器)。 RTC仅具有一秒的粒度和显着的延迟,许多系统没有RTC的粒度,但是它对随机性驱动程序没有影响。而且,如果不故意对其进行补丁以强制设置CR4.TSD,就不能禁用内核中的TSC,尽管我认为这可能甚至对环0代码也不起作用。实际上,您几乎可以执行Kconfig来显着削弱熵收集。即使杀死HPET也无害。

–森林
19-3-22在5:38



我的意思是说您可能是指时间戳计数器(TSC),而不是实时时钟(RTC)。

–森林
19-3-22在5:46



回顾该论文,它似乎是指熵池的初始化,它会在熵池“填充”之前影响在第一次启动时由/ dev / urandom生成的密钥。此池初始化是在启动时完成的。也许将其更改为“就像在第一次启动后的一分钟内生成密钥”会更清晰和更少歧义。

– Cody P
19 Mar 22 '19在6:11