【问题标题】:Using seed in PRNG在 PRNG 中使用种子
【发布时间】:2013-03-09 04:24:08
【问题描述】:

在 Java 中,我使用“SHA1PNRG”生成伪随机数。我不知道这个数字生成的内部工作。什么种子值最适合安全数字生成?我应该使用较小的数字作为种子还是使用较大的值作为种子?请善意给予适当的指导。

我的代码:

SecureRandom sr= SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(seed);

我使用sr.nextInt(int) 获取下一个值,seed 是一个长数据类型变量。

【问题讨论】:

    标签: java random cryptography


    【解决方案1】:

    NIST SP800-90A 在使用基于 SHA-1 的 Hash_DRBG(确定性随机位生成器)时建议种子长度为 440 位(即 55 个字节)。 (那里也描述了算法)。

    但这不仅与种子的长度有关,还与它的熵(“随机性”)有关。如果你用一个 440 位的零字符串初始化 DRBG,尽管它很长,但它是一个糟糕的选择。

    播种的目的是配置生成器的初始状态,使攻击者无法预测随机数的序列。请记住,所有过程都是确定性的,那么一旦任何人知道生成器的状态,他就能够从那时起重现随机序列。

    您可以使用 SecureRandom.generateSeed 方法计算种子,该方法依赖于当前操作系统提供的熵源(例如,SeedGenerator of OpenJDK 在 Linux 上使用 /dev/random,在 Windows 上使用 MS CryptoAPI)。

     SecureRandom sr= SecureRandom.getInstance("SHA1PRNG");     
     byte seed[] = random.generateSeed(55);
     sr.setSeed(seed);
    

    【讨论】:

    • 谢谢哈维尔。如果我使用 long 数据类型的种子而不是使用 byte 类型的种子,它是否会损害安全性?
    • 是的。首先,因为long 只有64 位,那么你的种子太短了。其次,因为nextLong() 根据生成器的当前状态返回一个伪随机数(而不是来自熵源的值)。如果您使用 nextLong 作为种子的来源,那么您几乎没有提供任何熵,因为您正在尝试用自身“改进”生成器。
    • 我认为这两种用法的结果是一样的。谢谢指正。
    【解决方案2】:

    你使用种子的什么数字并不重要。重要的是每次启动程序时您都为种子使用一个不同的编号。

    PRNG 或伪随机数生成器通过对种子执行计算来工作。它使用该计算的输出作为下一个随机数的种子,依此类推。 (这是一种简化,但它为您提供了正确的想法。)因此,如果您使用相同的种子,PRNG 将产生相同的数字序列。

    典型的种子来自系统时间,或者来自用户的按键或鼠标移动,或者每次程序运行时可能不同的其他值。

    【讨论】:

    • 谢谢亚当·利斯。现在知道了。
    • "系统时间" -- 不,这不应该用作种子。
    【解决方案3】:

    Maximin,如果您担心人们无法猜测种子(从而预测 PRNG 的输出),您应该使用实际随机的种子。例如,使用程序运行的时间是不安全的。

    您不应通过直接调用setSeed 来绕过内部播种机制。如果在调用java.security.SecureRandom.nextBytes(byte[]) 之前调用java.security.SecureRandom.setSeed(long)java.security.SecureRandom.setSeed(byte[]),则绕过内部种子机制,仅使用提供的种子生成随机数。

    查看 Amit Thesi 几年前关于此主题的有用博客文章 http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-05
      • 2021-11-10
      • 1970-01-01
      • 1970-01-01
      • 2016-06-03
      • 2014-09-16
      相关资源
      最近更新 更多