代码之家  ›  专栏  ›  技术社区  ›  rook

生成随机数最安全的种子是什么?

  •  61
  • rook  · 技术社区  · 14 年前

    什么是最安全的熵源种子随机数发生器?这个问题与语言和平台无关,适用于网络上的任何机器。理想情况下,我正在寻找云环境中的计算机或托管公司提供的服务器可用的源代码。

    要记住两个重要的弱点。使用时间发送随机数生成器违反了 CWE-337 CWE-339 .

    20 回复  |  直到 14 年前
        1
  •  89
  •   Thomas Pornin    14 年前

    以下是一些想法。如果你不耐烦,跳到最后的结论。

    安全性仅相对于攻击模型定义。我们需要一系列 n 比特,那是 n 关于攻击者的熵位:简单地说,任何可能的 2 n 从攻击者的角度来看,该序列的值具有相同的可能性。

    这是一个与 可供攻击者使用。生成和使用种子的应用程序(通常在PRNG中)知道确切的种子;种子是否“安全”不是种子的绝对属性,甚至不是种子生成过程的绝对属性。重要的是攻击者掌握的有关生成过程的信息量。根据不同的情况,这种信息水平差别很大;e、 g.在多用户系统上(比如类Unix系统,应用程序的硬件强制分离),精确的内存访问时间可以揭示一个名义上受保护的进程如何读取内存的信息。即使是远程攻击者也可以获得此类信息;这是 demonstrated (在实验室条件下)AES加密(典型的AES实现使用内部表,访问模式取决于密钥;攻击者强制缓存未命中,并通过服务器响应的精确计时来检测它们。

    必须考虑种子寿命。只要攻击者不知道种子,它就是安全的;这一属性事后必须成立。特别是,不可能从后续PRNG输出的摘录中恢复种子。理想情况下,即使在某个时刻获得完整的PRNG状态,也不应该提供PRNG事先产生的任何比特的线索。

    一旦 ,并在由防篡改硬件托管的安全PRNG中使用。

    不幸的是,这样的硬件是昂贵的(它被称为HSM,花费几百或几千美元),而且这种成本通常很难被证明是合理的(一个坏的种子不会阻止一个系统的运行;这是一个普遍存在的问题(安全的稳定性)。因此,人们习惯于选择“主要是软件”解决方案。由于软件不善于提供长期的保密存储,种子寿命被任意缩短:一个新的种子被周期性地获得。在 Fortuna ,这样的重播应该至少每兆字节产生一次伪随机数据。

    2混合

    0.5 ,位值相互独立)。相反,随机源在特定于源的集合中生成值。这些值可以被编码为位序列,但是你的钱不值得拥有 位的熵,你必须有值,当编码,使用远远超过 n 位。

    PRF 它接受任意长度的输入,并生成 n -位输出。这种加密安全的PRF被建模为 random oracle :简而言之,在计算上不可能在给定的输入上预测任何有关oracle输出的信息而不进行尝试。

    现在,我们有 hash functions SHA-2 函数(SHA-256、SHA-512…)被认为是安全的,但由于“长度扩展攻击”(给定)而偏离随机预言模型 ,可以计算 h(米| |米’) 对于部分约束的消息 不知情 ). 长度扩展攻击似乎没有为创建前映像或冲突提供任何捷径,但它表明这些哈希函数不是随机预言。对于 SHA-3 competition NIST表示,候选人不应允许这种“长度延长”。

    因此,混合步骤并不容易。目前,您最好的选择仍然是使用SHA-256或SHA-512,并在选择时切换到SHA-3(这应该发生在2012年年中左右)。

    三。来源

    计算机是确定性的机器。为了获得一些随机性,你必须混合一些物理世界的测量结果。

    哲学提示:在某些时候,你必须相信一些聪明的人,他们可能穿实验室的外套,或者拿薪水做基础研究。当你使用像SHA-256这样的散列函数时,你实际上是在信任一群密码学家,他们告诉你:我们寻找缺陷,非常困难,而且找了几年都没有发现。当你用盖革计数器测量一点衰变的放射性物质时,你相信一些物理学家说:我们很难找到预测下一个原子核何时爆炸的方法,但我们没有找到。请注意,在这种情况下,“物理学家”包括贝克勒尔、卢瑟福、玻尔或爱因斯坦等,而“真正的努力”意味着“一个多世纪的积累研究”,所以你在这里并不完全处于未经训练的领域。然而,人们仍然对安全抱有一点信心。

    Wikipedia ,至少)。

    除非有特殊的硬件,你必须使用你可能得到的任何物理事件。通常,您会使用按键、传入的以太网数据包、鼠标移动、硬盘访问。。。每个事件都有一些数据,发生在可测量的瞬间(现代处理器有非常精确的时钟,这要归功于周期计数器)。这些瞬间和事件数据内容可以作为熵源进行累积。对于操作系统本身(可以直接访问硬件)来说,这要比应用程序容易得多,因此收集种子的正常方法是询问操作系统(在Linux上,这称为 /dev/random /dev/urandom [都有优点也有问题,选择你的毒药];在Windows上,呼叫 CryptGenRandom() ).

    在添加 java.security.SecureRandom ; 由于Java在将应用程序代码与硬件隔离方面非常有效,因此获得随机种子是一项艰巨的挑战。通常的解决方案是让两个或三个线程同时运行并疯狂地切换线程,这样每秒线程切换的数量就有点随机了(实际上,这试图通过操作系统调度器操作的计时来提取随机性,这取决于机器上也发生了什么,包括硬件相关的事件)。这很不令人满意。

    与时间相关的度量的一个问题是,攻击者还知道当前时间是多少。如果攻击者具有对计算机的应用程序访问权限,那么他也可以读取循环计数器。

    www.google.com )并查看需要多长时间才能恢复(但这可能会被监视网络的攻击者观察到)。

    混合步骤的美妙之处在于,使用散列函数,熵只能累积;即使数据不是随机的,添加数据也没有什么坏处。通过hash函数尽可能多的填充。散列函数的速度非常快(一个好的SHA-512实现在一台典型的PC上,使用一个内核,处理速度将超过150mb/s),而且种子植入并不经常发生。

    使用 HSM . 它们花了几百或几千美元,但你的秘密不比这值钱得多吗?HSM包括RNG硬件,运行PRNG算法,并存储具有抗篡改能力的种子。此外,大多数HSM已经通过了各种国家法规的认证(如美国的FIPS 140和欧洲的EAL水平)。

    如果你是如此便宜,你不会买一个HSM,或者如果你想保护数据,这实际上是不太值得,然后建立一个加密安全PRNG使用种子散列获得 物理测量。任何来自某个硬件的数据都应该与获取数据的瞬间(读取“循环计数器”)一起散列。你应该在这里按兆字节散列数据。或者,最好是这样做 做到这一点:只需使用操作系统提供的工具,其中已经包含了这样的代码。

        2
  •  51
  •   rook    14 年前

    最安全的种子是具有最高级别的熵(或最多无法预测的比特数)的种子。时间通常是一个坏种子,因为它的熵很小(也就是说,如果你知道事务发生的时间,你可以猜测时间戳在几位之内)。硬件熵源(例如来自衰变过程)非常好,因为它们为种子的每一位产生一位熵。

    您可以使用的一些源有:以微秒为单位的当前时间(通常非常低的熵为1/2位,具体取决于分辨率和攻击者猜测的容易程度)、UI事件的到达间隔时间等。

    操作系统源(如/dev/random和windowscapi随机数生成器)通常提供这些低熵源的预混合源,例如Windows生成器 CryptGenRandom 包括:

    • 当前进程ID(GetCurrentProcessID)。
    • 当前线程ID(GetCurrentThreadID)。
    • 自启动时以来的计时计数(GetTickCount)。
    • 当前时间(GetLocalTime)。
    • 各种高精度性能 计数器(QueryPerformanceCounter)-
    • 用户环境的MD4散列 计算机名和搜索路径。[…]-
    • 高精度内部CPU计数器,如RDTSC、RDMSR、RDPMC

    Fortuna 发电机。它特别使用限制风险的策略,如果任何熵源被破坏。

        3
  •  15
  •   Vinko Vrsalovic    14 年前

    • EntropyPool
    • 使用坏种子(即时间)并将其与其他仅为您所知的数据相结合(例如,使用机密和其他一些标准(如PID或应用程序/操作系统的内部状态)散列时间,因此它不一定随时间增减)
        4
  •  8
  •   msw    14 年前

    作为一次性记事本的一个有趣的做法,每当我从事间谍活动时,我都有一个系统,我只需要传达几个字母。例如,上一次我向大芬威克公国出售制造烤面包机的秘密计划时,我只需要小声说:

    埃诺

    http://is.gd/enonH- (这是一个“安全”的扩展URL,它会将您带到is.gd扩展页,该扩展页又指向一个完全SFW的青蛙图像)。这给了我们409k位的一次性pad或者-如果我在耳语“enonH”时眨眼-她知道把图像的散列值作为我下一次传输的解码键。

    由于JPEG图像的压缩,它们往往是相对较好的熵源,如 ent


    熵=7.955028位

    最佳压缩将减少 此51092字节文件的大小为0 百分比。

    51092的卡方分布 样本数为4409.15,随机抽取 超过该值0.01%

    129.0884(127.5=随机)。
    2.81%)。
    序列相关系数为0.052738(共 不相关=0.0)。不相关=0.0)。

    再加上我让她看到的几乎不可能猜到的画面,我的秘密烤面包机计划对那个男人来说是安全的。

        5
  •  7
  •   rook    14 年前

    答案是 /dev/random 在Linux机器上。这非常接近于“真实”随机数生成器,其中 /dev/urandom 可以是 如果熵池耗尽,由PRNG生成。以下引述摘自 Linux kernel's random.c 这整个文件是一个美丽的阅读,大量的评论。其本身的代码是从PGP中采用的。它的美不受C的约束,C的约束以访问器包装的全局结构为标志。这是一个简单的令人敬畏的设计。

    这种习惯会增加环境影响 来自设备驱动程序等的噪音,以及 返回合适的随机数 用于加密。除了 明显的密码用途,这些 数字也有利于播种 TCP序列号和其他位置 希望有 不仅是随机的,而且

    操作理论

    计算机是非常可预测的设备。因此,这是非常困难的
    计算机——相对于
    伪随机数,可以
    算法。不幸的是,这是非常困难的 攻击者很容易猜到 伪随机数序列
    这是不可接受的。 因此,我们必须努力 “环境噪音”来自 计算机环境,必须 外部攻击者很难 观察,并用它来产生 随机数。在Unix中 环境,最好从

    来自环境的随机性的来源包括键盘间
    一些中断和其他事件 两者都是不确定的 测量。来自这些的随机性 使用类似于CRC的 功能。这不是 密码学上很强,但实际上 假设随机性为 不是恶意选择的,而且速度很快 足够让你的开销 每次打断都很合理。 熵池,例程保持 估计有多少位 随机数发生器内部

    当需要随机字节时,它们是通过获取SHA来获得的
    熵的内部状态 游泳池。据信是的 在计算上无法推导 SHA的输入来自其输出。即使 一些聪明的方法,只要金额 从生成器返回的数据 小于中固有的熵
    池中,输出数据 例行程序减少其内部 估计有多少位“真” 熵池,因为它输出随机 数字。 如果这个估计值变为零,例程仍然可以生成随机变量 数字;但是,攻击者可能(至少 至少在理论上)能够推断 发电机的未来输出 成功的密码分析 对绝大多数人有用 目的。

    ...

        6
  •  5
  •   Seva Alekseyev    14 年前

    写一个互联网广播客户端,使用随机样本从广播。有几个站可供选择和/或返回。

        7
  •  4
  •   Merlyn Morgan-Graham    14 年前
        8
  •  3
  •   James    14 年前

    如果你读了密码理论,很明显最安全的种子是由混沌事件产生的。纵观最近的历史,秘密行动利用了所谓的 "One-time pad" 这被证明是不可能破解的。通常情况下,这些都是通过散布在偏僻地方的各种大气监听站产生的。大气噪声足够混沌,可以认为是随机的。这种方法的主要问题是,一次性pad的物流是相当可观的。

        9
  •  2
  •   James Black    14 年前

    好的,假设客户端需要一个强大的种子,并且您正在使用云计算,这里有一个解决方案,对于一些硬件随机数生成器,您可以在这里查看:

    http://en.wikipedia.org/wiki/Hardware_random_number_generator

    因此,这假设每个客户机都有一个公钥/私钥对,其中服务器知道每个客户机的公钥。 要生成一个键,您可以使用类似于PGP的方法,在一开始,您可以根据某人键入的键笔划之间的时间差,因为这是不可猜测的。

    服务器使用硬件生成器,使用公钥对其进行加密,并使用服务器的私钥对此进行签名。 然后客户端可以验证它来自何处,然后解密它。

    你最好的办法就是看看 计算机程序设计艺术 或者任何一本数值方法书,或者看看Bruce Schneier写的东西,比如以下链接: http://www.schneier.com/blog/archives/2006/06/random_number_g.html http://www.cryptosys.net/rng_algorithms.html http://www.schneier.com/blog/archives/2006/06/random_number_g.html http://www.schneier.com/blog/archives/2006/06/random_number_g.html 软件中随机数生成的建议, ftp://ftp.rsasecurity.com/pub/pdfs/bull-1.pdf

    你也可以考虑让Crypto++来生成,或者至少看看魏岱是怎么做到的, http://www.cryptopp.com/

        10
  •  2
  •   Alix Axel    14 年前

    Random.org 提供一个真正的随机数发生器 web service

    你每天可以免费获得20万个随机比特,最多可以达到100万个随机比特的上限,然后你就可以加满你的帐户,每美元可以便宜到400万个比特。

        11
  •  2
  •   Ma99uS    14 年前

    4-由非常随机的骰子卷选择。:-)

        12
  •  1
  •   UnixShadow    14 年前

    简单的解决方案,如果没有额外的随机硬件可用。

    使用毫秒、mouseX和mouseY生成种子。

        13
  •  1
  •   Dominik Weber    14 年前

    但由于硬件的需要,目前还没有语言和平台无关的答案。

    因此,第一步是确定您将使用哪种语言。

    根据您的安全需要,请对“在线”来源感到厌倦,因为对于未经验证的在线来源,中间人可能是一个严重的威胁。

        14
  •  1
  •   Steven Sudit    14 年前

    你最安全的方法来自大自然。也就是说,发生在你的计算机系统之外的事情,超出了我们预测其模式的能力。

    例如,许多研究人员 Cryptographically secure PRNGs 将使用放射性衰变作为模型,其他人可能会研究分形,等等。现有的方法 creating true RNGs

    我最喜欢的实现PRNG的方法之一是通过用户与计算机的交互。例如,这篇文章不是我过去一系列文章中的前沿工程可以预先确定的。我把鼠标放在屏幕上的地方很随意,它留下的痕迹也很随意。从用户交互的角度来看是。通过使用用户输入的“群”并计算它的“向量”,可以减轻提供特定输入的方法的滥用,从而生成特定的数字,只要您的系统中没有每个用户都是Eve,就可以了。这不适用于许多应用程序,因为您的数字池与用户输入成正比。实现这一点可能有自己的问题。

    1. 如前所述,辐射
    2. Atmosphere
    3. What's going on within the system 埃格。

    安全的种子来自大自然。

    编辑: 基于您正在做的事情,我可能建议您使用云服务器的EDG的聚合。

        15
  •  1
  •   Steven Sudit    14 年前

    首先,您需要定义随机数生成器的实际用途,以及为什么您认为必须通过如此高的安全标准?我问的原因是,你提到从罐头中挑选它-如果你确实是出于安全目的使用它,那么确保来源和渠道的安全比任何人的挑选都重要得多。

    http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.97.6594&rep=rep1&type=pdf http://www.springerlink.com/index/q29t6v1p45515186.pdf

    或者抓取你在网上找到的任何可重新配置的GOST密码源代码,然后你要么只给它一个基本种子(比如连接的“ticker”加上一个web服务器节点ID(如果它在一个web服务器场中)再加上任何internet新闻网站上的一部分响应,它会一直改变头条新闻,要么你可以给它一个高度控制的初始种子(你可以这样做)并使用轻伪随机序列来选择进一步的密码配置。即使是国家安全局也无法破解这个密码:-),因为它总是一个不同的密码。为了实际的加密目的,人们实际上必须使用非常受控的初始种子,以便能够复制序列进行验证。这就是我们回到第一项的地方-保护源和分发。

        16
  •  1
  •   Sergey G    14 年前

    使用 random.org 真正的随机数在互联网上的任何人 它们还有一个HTTP API,您可以使用它。他们提供免费和有偿服务。

    免责声明: 我与random.org没有任何关系

        17
  •  1
  •   juniz    13 年前

    对于Linux,答案是/dev/random(在Windows中,我认为等价的是CryptGenRand)。

    如果您想了解我们的解决方案,请访问我们的网站(www.sqrtech.com)或联系我们info@sqrtech.com.

    朱利安

        19
  •  0
  •   Mark Mullin    14 年前

    这是猜测!如果我弄错了,请更正

    此时,UUID/GUID的官方算法返回一个通过加密哈希函数运行的结果—它使用已知信息(如时间、mac addr和计数器)来形成UUID/GUID,然后通过加密哈希函数运行此结果,以确保无法提取mac地址。

        20
  •  0
  •   zccool4718    14 年前

    ((PI X当前线程ID)X当前进程ID)/勾号计数)X PI