【问题标题】:Could a truly random number be generated using pings to pseudo-randomly selected IP addresses?可以使用 ping 到伪随机选择的 IP 地址生成真正的随机数吗?
【发布时间】:2008-09-26 01:57:39
【问题描述】:

提出的问题是在第二年的 Comp Science 讲座中提出的,当时讨论了在确定性计算设备中生成数字的可能性。

这是唯一不依赖于非商品级硬件的建议。

随后,没有人会拿自己的名誉来明确支持或反对它。

任何人都关心支持或反对。如果是这样,是否可以提及可能的实现方式?

【问题讨论】:

  • 不太确定熔岩灯是否被视为商品级硬件,但lavarnd.org 呢!
  • 上帝不掷骰子 - A.Einstein ;D
  • @david:事实上,他确实这样做了 - W. Heisenberg
  • @lacop:“爱因斯坦,别再告诉上帝该做什么了!” - 尼尔斯·玻尔
  • 一个非常简短的回答:不够统一。

标签: algorithm theory random


【解决方案1】:

没有。

您网络上的恶意机器可能会使用 ARP 欺骗(或许多其他技术)来拦截您的 ping,并在特定时间后回复它们。然后他们不仅会知道你的随机数是什么,而且还会控制它们。

当然,您的本地网络的确定性仍然存在问题,因此在实践中可能并不那么容易。但是,由于在互联网上 ping 随机 IP 没有任何好处,因此您不妨从以太网流量中获取熵。

从连接到机器的设备中提取熵是一个经过充分研究的原理,各种设备和测量方法的优缺点可以是例如从 /dev/random 的实现中窃取。

[编辑:作为一般原则,在从事安全基础工作时(并且对大量真正随机数据的唯一实际需求是与安全相关的),您必须假设一个非常好的- 资源丰富、意志坚定的攻击者将竭尽全力破坏您的系统。

为了实际的安全性,您可以假设没有人那么想要您的 PGP 密钥,并在安全性与成本之间进行权衡。但是在发明算法和技术时,你需要给他们最强大的安全保证,这是他们可能面临的。因为我可以相信某个地方的某个人可能非常想要别人的私钥来构建这个工具包来击败你的提议,所以我不能接受它作为对当前最佳实践的进步。 AFAIK /dev/random 非常接近在廉价家用 PC 上生成真正随机数据的最佳实践]

[另一个编辑:它在 cmets 中建议 (1) 任何 TRNG 都可能影响物理过程,并且 (2) 安全问题无论如何都不适用于这里.

(1) 的答案是,在任何实际硬件上都可能比 ping 响应时间好得多,并且可以更快地收集更多熵,因此该提议不是解决方案。在 CS 术语中,很明显您无法在确定性机器上生成随机数,这就是引发问题的原因。但是在 CS 术语中,具有外部输入流的机器在定义上是不确定的,所以如果我们谈论 ping,那么我们就不是在谈论确定性机器。因此,有必要查看真实机器的真实输入,并将它们视为随机性的来源。无论您的机器是什么机器,原始 ping 时间在可用资源列表中都不高,因此可以在担心更好的资源有多好之前排除它们。与假设您自己的硬件没有被破坏相比,假设网络没有被破坏是一个更大(也是不必要的)假设。

(2)的答案是哲学的。如果您不介意您的随机数具有可以随心所欲而不是偶然选择的属性,那么这个建议是可以的。但这不是我对“随机”一词的理解。仅仅因为某些东西不一致并不意味着它一定是随机的。

最后,按照要求解决提案的实施细节:假设您接受随机 ping 时间,您仍然不能使用未处理的 ping 时间作为 RNG 输出。你不知道它们的概率分布,而且它们肯定不是均匀分布的(这通常是人们希望从 RNG 获得的)。

因此,您需要确定您愿意依赖的每个 ping 的熵位数。熵是随机变量的精确定义的数学属性,可以合理地被认为是衡量它实际上有多“随机”的量度。在实践中,您会找到一个您满意的下限。然后将许多输入散列在一起,并将其转换为小于或等于输入的总依赖熵的输出位数。 “总计”并不一定意味着总和:如果输入在统计上是独立的,那么它就是总和,但对于 ping 而言,这不太可能是这种情况,因此您的熵估计的一部分将考虑相关性。这种散列操作的老大哥被称为“熵收集器”,所有好的操作系统都有一个。

但是,如果您使用这些数据来为 PRNG 播种,并且 PRNG 可以使用任意大的种子输入,那么您就不必进行哈希处理,因为它会为您执行此操作。如果你想知道你的种子值有多“随机”,你仍然需要估计熵——你可以使用世界上最好的 PRNG,但它的熵仍然受到种子熵的限制。]

【讨论】:

  • 这与任何 TRNG 有何不同?如果有人在你的巢穴里大便,那么减轻攻击就没有意义了,因为为时已晚。
  • 怎么说攻击者不是你的ISP?然后他们只是捕获所有 ICMP 数据包,并在 100 毫秒后返回它们?它仍然会严重影响熵。
  • 这不是安全问题。说不可能因为存在安全问题是没有意义的,尽管指出它们会提供有用的信息。
  • @Tyler:问题是“这会产生真正的随机数据吗?”。答案是“一般情况下不会。有时数据是由人选择的”。无论您是否使用安全一词,这都是事实。在分析任何算法的失败案例时,我总是从恶意攻击者的角度考虑。
  • @marxidad:正确,但这是关于便便的合理性。网充满了便便,以一种依赖于没有便便的方式使用它几乎是幼稚的。使用 bog-standard /dev/random 收集的熵远比使用 ping 响应时间更难。
【解决方案2】:

随机数太重要了,不能碰运气。

或外部影响/操纵。

【讨论】:

  • +1 "随机数太重要了,不能碰运气。"可能是关于 SO 的最佳答案。
  • “随机数的生成太重要了,不能靠运气。” ——约翰·冯·诺依曼
【解决方案3】:

简答

单独使用 ping 计时数据不会是真正随机的,但它可以用作entropy 的来源,然后可以用来生成真正的随机数据。

加长版

ping 时间有多随机?

就其本身而言,来自网络操作(例如 ping)的计时数据不会均匀分布。 (而且选择随机主机的想法是不切实际的 - 许多主机根本不会响应,主机之间的差异可能很大,响应时间范围之间存在差距 - 想想卫星连接)。

但是,虽然时间分布不会很好,但数据中会存在一定程度的随机性。或者换句话说,存在information entropy 级别。将时序数据输入随机数生成器来播种是个好主意。那么存在什么级别的熵呢?

对于大约 50 毫秒的网络计时数据,测量到最接近的 0.1 毫秒,值的扩展为 2 毫秒,您有大约 20 个值。向下舍入到最接近的 2 次幂(16 = 2^4),每个计时值有 4 位熵。如果它用于任何类型的安全应用程序(例如生成加密密钥),那么我会保守地说每次读取只有 2 或 3 位熵。 (注意我这里做了一个非常粗略的估计,忽略了被攻击的可能性)。

如何生成真正随机的数据

对于真正的随机数,您需要将数据发送到按照/dev/random 设计的东西中,它将收集熵,将其分布在数据存储中(使用某种hash function,通常是secure one )。同时,熵估计增加。因此,对于 128 位 AES 密钥,在熵池有足够的熵之前需要 64 次 ping 时间。

为了更加健壮,您可以添加来自键盘和鼠标使用情况、硬盘响应时间、主板传感器数据(例如温度)等的计时数据。它增加了熵收集的速率,使攻击者难以攻击监控所有熵源。事实上,这就是现代系统所做的。 second comment of this post 中列出了 MS Windows 熵源的完整列表。

更多阅读

要讨论对随机数生成器的(计算机安全)攻击以及密码安全随机数生成器的设计,您可能会比阅读Bruce Schneier 和 John Kelsey 撰写的 yarrow paper 做得更糟。 (BSD 和 Mac OS X 系统使用 Yarrow)。

【讨论】:

    【解决方案4】:

    没有。

    拔掉网线(或/etc/init.d/networking stop),熵基本降为零。

    对它正在 ping 的机器执行拒绝服务攻击,您还可以获得可预测的结果(ping 超时值)

    【讨论】:

      【解决方案5】:

      我想你可以。有几点需要注意:

      • 即使 ping 随机 IP 地址,前几跳(从您到 ISP 网络中第一个真正的 L3 路由器)对于每个数据包都是相同的。这为往返时间设置了一个下限,即使您在第一个存在点对数据中心中的某些内容执行 ping 操作。所以你必须小心规范时间,往返有一个下限。
      • 您还必须小心网络中的流量整形。路由器中典型的漏桶实现每 M 微秒释放 N 个字节,这有效地将您的时间扰乱到特定的时隙而不是连续的时间范围内。因此,您可能需要丢弃时间戳的低位。

      但是,我不同意商品硬件中没有好的熵来源的前提。过去几年的许多 x86 芯片组都包含随机数生成器。我熟悉的那些使用相对敏感的 ADC 来测量芯片上两个不同位置的温度,然后减去它们。这种温差的低位可以显示(通过卡方分析)是强随机的。当您增加系统上的处理负载时,整体温度会上升,但芯片的两个区域之间的差异仍然不相关且不可预测。

      【讨论】:

      • 同意。当时会有一个非常有偏差的范围,所以我预计熵不会超过 1-2 位。
      【解决方案6】:

      我见过的商品硬件随机性的最佳来源是一个人从他的网络摄像头上取下过滤器或其他东西,在镜头上涂上不透明的胶水,然后能够轻松地从宇宙射线的撞击中检测到单个白色像素CCD。它们尽可能接近完全随机,并通过量子效应免受外部窥探。

      【讨论】:

      • 漫画光线?这确实有点有趣;)用网络摄像头制作的宇宙射线探测器听起来很酷,你有链接吗?
      • 或者可能只是来自传感器的随机噪声 :)
      • 你认为随机噪声来自哪里?
      • 不,这不是玩笑。我听说了,阅读了论文,遵循了理论。它本质上是一个热噪声检测器。这几乎是随机的。
      【解决方案7】:

      一个好的随机数生成器的一部分是所有数字的概率相等为 n -> 无穷大。

      因此,如果您打算生成随机字节,那么从一个好的 rng 中获得足够的数据,每个字节应该有相同的返回概率。此外,返回的某些数字不应该有模式或可预测性(在某些时间段内的概率峰值)。

      我不太确定使用 ping 您将测量什么来获取随机变量,是响应时间吗?如果是这样,您可以确定某些响应时间或响应时间范围会比其他响应时间更频繁,因此可能会产生不安全的随机数生成器。

      【讨论】:

      • 消除偏见是一个经过充分研究的领域。最简单的算法是将有偏差的比特流分成对,将 01 转换为 1,将 10 转换为 0,并忽略 11 和 00 对。只要连续位是独立的,这适用于任何位流。
      【解决方案8】:

      如果您想要商品硬件,您的声卡应该可以做到。只需调高模拟输入的音量,您就有了便宜的白噪声源。无需网络的廉价随机性。

      【讨论】:

        【解决方案9】:

        测量某物以生成随机种子的方法似乎是一个不错的方法。 O'Reilly 的书Practical Unix and Internet Security 提供了一些类似的确定随机种子的附加方法,例如要求用户键入几个击键,然后测量击键之间的时间。 (书中指出,PGP 使用这种技术作为其随机性的来源。)

        我想知道系统 CPU 的当前温度(测量到小数点后很多位)是否可以成为随机种子的可行组件。这种方法的优点是不需要访问网络(因此当网络连接断开时随机生成器不会变得不可用)。

        但是,CPU 的内部传感器可能不太可能将 CPU 温度准确测量到足够的小数位,以使该值作为随机数种子真正可行;至少,不是问题中提到的“商品级硬件”!

        【讨论】:

        • 准确性无论如何都无关紧要。那么如果偏离 2 度呢?
        • @MSalters,我认为准确性很重要,不是因为结果需要完全准确,而是因为例如如果实际温度为 65.473806 度,您不希望将该值报告为 65.474;那么可能的值集将太小而无法生存/有用。
        • 这是精确度,不是准确度。
        【解决方案10】:

        它不如使用大气噪声,但它仍然是真正的随机,因为它取决于以随机不可重复行为而臭名昭著的网络特性。

        有关随机性的更多信息,请参阅Random.org

        这是一个实现的尝试:

        @ips  : list = getIpAddresses();
        @rnd         = PseudorandomNumberGenerator(0 to (ips.count - 1));
        
        @getTrueRandomNumber() { ping(ips[rnd.nextNumber()]).averageTime }
        

        【讨论】:

          【解决方案11】:

          在将往返 ping 视为熵之前,我会更早使用 ISAAC 之类的东西作为更强的 PRNG。就像其他人所说的那样,有人不仅要猜你的数字,而且还可能在不同程度上控制它们,这太容易了。

          存在其他重要的熵来源,其他人已经提到过。没有提到的一个(可能不实用)是从板载音频设备中采样噪声。即使没有连接麦克风,它通常也会有点吵。

          我经过 9 轮尝试为我正在编写的客户端/服务器 RPC 机制提出一个强大(且快速)的 PRNG。双方都有一个相同的密钥,由 1024 行 32 个字符的密码组成。客户端将发送 AUTH xx,服务器将返回 AUTH yy .. 双方都知道使用哪两行密钥来生成河豚秘密(+盐)。然后服务器将发送整个密钥(加密)的 SHA-256 摘要,客户端知道它正在与具有正确密钥的东西交谈..会话继续。是的,对中间人的保护非常弱,但是对于设备的使用方式来说,公钥是不可能的。

          因此,您有一个必须处理多达 256 个连接的非阻塞服务器。.. PRNG 不仅必须强大,而且必须快速。在客户端使用较慢的方法收集熵并没有那么困难,但在服务器中无法提供。

          所以,我不得不问一下你的想法......它有多实用?

          【讨论】:

            【解决方案12】:

            没有数学计算可以产生随机结果,但在“现实世界”中,计算机不仅仅只是处理数字......只要有一点创造力,应该就有可能产生随机结果重现或预测确切结果的已知方法。

            我见过的在所有系统上通用的最容易实现的想法之一是使用来自计算机声卡线路输入/麦克风端口的静态。

            其他想法包括热噪声和高速缓存行的低级时序。许多带有 TPM 芯片的现代 PC 已经板载了加密质量的硬件随机数生成器。

            我对 ping 的下意识反应(尤其是使用 ICMP 时)是您的作弊过于明目张胆。到那时,您不妨拿出一个吉格计数器并使用背景辐射作为您的随机源。

            【讨论】:

              【解决方案13】:

              是的,这是可能的,但是……魔鬼在细节中。

              如果要生成 32 位整数,则需要收集 >32 位的熵(并使用足够的混合函数来使熵散布,但这是已知且可行的)。最大的问题是:

              ping 时间有多少熵?

              这个问题的答案取决于对网络和您的攻击模型的各种假设,并且在不同的情况下有不同的答案。

              如果攻击者能够完全控制 ping 时间,那么每次 ping 的熵为 0 位,并且无论混合多少,总熵都不会达到 32 位。如果他们对 ping 时间的控制不够完美,您将获得一些熵,并且(如果您不高估所收集的熵量)将获得完全随机的 32 位数字。

              【讨论】:

                【解决方案14】:

                YouTube 显示正在运行的设备:http://www.youtube.com/watch?v=7n8LNxGbZbs

                随机是,如果没有人可以预测下一个状态。

                【讨论】:

                  【解决方案15】:

                  虽然我不能明确地支持或反对,但这个实现有它的问题。

                  这些IP地址是从哪里来的,如果是随机选择的,如果不回复或者回复迟了会发生什么,是不是意味着随机数出现的速度会比较慢。

                  此外,即使您将 100.000 个结果制作成可视图表并计算出这些数字之间没有相关性或相关性很少,但这并不意味着它是真正随机的。正如dilbert 所解释的那样:)

                  【讨论】:

                    【解决方案16】:

                    我并不觉得它是随机性的好来源。

                    您会使用什么指标 - 显而易见的指标是响应时间,但您可以合理预期的值范围很小:几十毫秒到几千毫秒。响应时间本身将遵循钟形曲线,并且不会随机分布在任何间隔(您将如何选择间隔?)因此您必须尝试从数字中选择一些“随机”位。

                    LSB 可能会为您提供随机比特流,但您必须考虑时钟粒度问题 - 可能由于中断的工作方式,您在某些系统上总是会得到 2ms 的倍数。

                    可能有更好的“有趣”方法来获取随机位——也许谷歌搜索一个随机词,抓取第一页并从页面中选择第 N 位。

                    【讨论】:

                      【解决方案17】:

                      呃,我发现这种问题很快就引发了关于“真正随机”含义的讨论。

                      我认为测量 ping 会产生质量不错的随机位,但速度不足以发挥很大作用(除非您愿意进行一些严重的 DDOS 攻击)。

                      而且我认为它不会比测量计算机的模拟/机械特性或操作它的肉袋的行为更随机。

                      (编辑)在实际操作中,这种方法可以让您发现网络上的某个人可能会操纵您的“随机”数字生成器。

                      【讨论】:

                      • @MikeF:我实际上非常发现“肉袋”是随机数的来源。它非常擅长生成随机数。 :)
                      【解决方案18】:

                      在我看来,真正的随机性是不可言喻的——没有办法知道一个序列是否是随机的,因为根据定义它可以包含 任何东西,无论多么不可能。保证特定的分布模式减少随机性。 “模式”这个词有点夸张。

                          I MADE U A RANDOM NUMBER
                                 BUT I EATED IT
                      

                      【讨论】:

                      • 缺乏模式决定了它的随机性。
                      • 啊,但是你如何从真实的模式中分辨出模式的表象呢?我亲眼见过一个双陆棋选手连续打出 22 个双打。发生这种情况的可能性非常大,但它确实发生了。
                      • 随机性似乎难以言喻,但统计学家已经将其消除了。有几种公认的随机性测试 - 请参阅 en.wikipedia.org/wiki/Randomness_tests
                      【解决方案19】:

                      随机性不是二元属性——它是一个介于 0 和 1 之间的值,用于描述预测流中下一个值的难度。

                      询问“如果我基于 ping,我的值会有多随机?”实际上是在问“ping 有多随机?”。您可以通过收集足够大的数据集(例如 100 万次 ping)并及时绘制它们的分布曲线和行为来估计这一点。如果分布平坦且行为难以预测,则数据似乎更加随机。越颠簸的分布或可预测的行为表明随机性越低。

                      您还应该考虑样本分辨率。我可以想象结果会以某种方式四舍五入到毫秒,因此对于 ping,您可以有 0 到 500 之间的整数值。这不是很多分辨率。

                      在实际方面,我建议不要这样做,因为可以预测和操纵 ping,从而进一步降低它们的随机性。

                      一般来说,我建议不要“滚动你自己的”随机生成器、加密方法和散列算法。尽管看起来很有趣,但大部分都是非常令人生畏的数学。

                      至于如何构建一个非常好的熵发生器——我认为这可能必须是一个密封的盒子,它可以输出某种原子或亚原子级别的交互结果。我的意思是,如果您使用敌人也可以轻松读取的熵源,那么他只需要找出您的算法即可。任何形式的连接都是可能的攻击向量,因此您应该将熵源放置在尽可能靠近使用它的服务的位置。

                      【讨论】:

                        【解决方案20】:

                        您可以使用 XKCD 方法:

                        【讨论】:

                          【解决方案21】:

                          我得到了一些使用 traceroute 创建随机数的代码。我也有一个使用 ping 的程序。一年多前,我为一个班级项目做了这件事。它所做的只是在和地址上运行 traceroute,它占用 ms 次中最小的 sig 数字。它在获取随机数方面效果很好,但我真的不知道它与真正的随机数有多接近。

                          这是我运行时得到的 8 个数字的列表。

                          455298558263758292242406192

                          506117668905625112192115962

                          805206848215780261837105742

                          095116658289968138760389050

                          465024754117025737211084163

                          995116659108459780006127281

                          814216734206691405380713492

                          124216749135482109975241865

                          #include <iostream>
                          #include <string>
                          #include <stdio.h>
                          #include <cstdio>
                          #include <stdlib.h>
                          #include <vector>
                          #include <fstream>
                          
                          using namespace std;
                          
                          int main()
                          {
                          system("traceroute -w 5 www.google.com >> trace.txt");
                          
                          string fname = "trace.txt";
                          ifstream in;
                          string temp;
                          
                          vector<string> tracer;
                          vector<string> numbers;
                          
                          in.open(fname.c_str());
                          while(in>>temp)
                          tracer.push_back(temp);
                          
                          system("rm trace.txt");
                          
                          unsigned index = 0;
                          
                          string a = "ms";
                          while(index<tracer.size())
                          {
                          if(tracer[index]== a)
                          numbers.push_back(tracer[index-1]);
                          ++index;
                          }
                          
                          
                          std::string rand;
                          
                          for(unsigned i = 0 ; i < numbers.size() ; ++i)
                          {
                          std::string temp = numbers[i];
                          int index = temp.size();
                          rand += temp[index - 1];
                          }
                          
                          cout<<rand<<endl;
                          
                          return 0;
                          
                          }
                          

                          【讨论】:

                            【解决方案22】:

                            很简单,由于网络遵循规定的规则,结果不是随机的。

                            网络摄像头的想法听起来(有点)合理。 Linux 用户通常建议仅使用未连接麦克风的声卡中的随机噪声。

                            【讨论】:

                              【解决方案23】:

                              这是我的建议:

                              1- 选择离您所在位置尽可能远的网站。例如如果您在美国,请尝试一些在马来西亚、中国、俄罗斯、印度等国家/地区拥有服务器 IP 的网站。流量大的服务器比较好。

                              2- 在您所在国家/地区的高互联网流量期间(在我的国家/地区,大约是晚上 7 点到 11 点)多次 ping 这些网站,获取每个 ping 结果(仅使用整数值)并计算模数 2它(即从每个 ping 操作中你得到一个位:0 或 1)。

                              3-重复这个过程几天,记录结果。

                              4- 收集您从所有 ping 中获得的所有位(可能您将获得数十万位)并从中选择您的位。 (也许你想通过使用上面提到的相同方法的一些数据来选择你的位:))

                              小心:在你的代码中你应该检查超时..etc

                              【讨论】:

                                猜你喜欢
                                • 2016-03-08
                                • 1970-01-01
                                • 2012-03-03
                                • 2012-05-03
                                • 2017-10-02
                                • 2010-11-17
                                • 1970-01-01
                                • 1970-01-01
                                • 2012-02-09
                                相关资源
                                最近更新 更多