【问题标题】:SecureRandom safe seed in JavaJava中的SecureRandom安全种子
【发布时间】:2012-08-28 06:31:46
【问题描述】:

这段代码安全吗?

 SecureRandom randomizer = new SecureRandom(String.valueOf(new Date().getTime()).getBytes());

这是实例化安全随机种子的正确方法吗?

【问题讨论】:

    标签: java security encryption random cryptography


    【解决方案1】:

    我认为最好让 SecureRandom 自己播种。这是通过在创建后立即调用 nextBytes 来完成的(调用 setSeed 会阻止这种情况)。

    final byte[] dummy = new byte[512];
    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.nextBytes(dummy);
    

    您想使用 SHA1PRNG,因为它保证了快速的非阻塞实现,即使在 Linux 上也是如此,默认情况下不是这样。

    【讨论】:

    • 如果nextBytes() 调用只是为了播种,我不会使用 512 byes,但出于效率原因只使用 1。
    【解决方案2】:

    不,您应该避免使用 SecureRandom(byte[]) 构造函数。它既不安全也不便携。

    它是不可移植的,因为它在 Windows 和其他操作系统上的行为不同。

    在大多数操作系统上,默认算法是“NativePRNG”,它从操作系统(通常是"/dev/random")获取随机数据并忽略您提供的种子。

    在 Windows 上,默认算法是“SHA1PRNG”,它将您的种子与计数器结合起来并计算结果的哈希值。

    在您的示例中这是个坏消息,因为输入(当前 UTC 时间,以毫秒为单位)的可能值范围相对较小。例如,如果攻击者知道 RNG 是在过去 48 小时内播种的,他们可以将种子缩小到小于 228 个可能的值,即您只有 27 位熵。

    另一方面,如果您在 Windows 上使用了默认的 SecureRandom() 构造函数,它将调用本机 CryptoGenRandom 函数来获取 128 位种子。因此,通过指定您自己的种子,您已经削弱了安全性。

    如果您真的想覆盖默认种子(例如用于单元测试),您还应该指定算法。例如

    SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
    sr.setSeed("abcdefghijklmnop".getBytes("us-ascii"));
    

    另见How to solve performance problem with Java SecureRandom?
    还有这篇博文:http://www.cigital.com/justice-league-blog/2009/08/14/proper-use-of-javas-securerandom/

    【讨论】:

    • 请注意,您提供的代码确实使用编码字符串作为输入来初始化伪随机生成器。所以它每次都会创建相同的随机数。我认为您的本意是要准确显示这一点,但是您可能希望在答案中更清楚地说明这一点(因为它肯定不安全)。如果任何其他提供商提供"SHA1PRNG",也可能会有所不同,因此在这方面它有点危险。
    • @MaartenBodewes 为什么你认为使用“NativePRNG”时会忽略种子?
    • @AlikElzin-kilaka 无法通过/dev/random 使用用户提供的种子。本机 Windows RNG 可以,但是当我发布这个答案时,JRE 没有利用这一点。那是 4 年前的事了,所以从那以后它可能已经改变了。
    【解决方案3】:

    该代码相当安全,因为它不只是使用给定的种子来为随机发生器播种。

    它并不比仅仅使用更随机。

    SecureRandom randomizer = new SecureRandom();
    

    【讨论】:

    • 是的,可能使用默认值更好——假设算法的设计者会选择一个好的播种方案。上面的方案可能会通过转换为字符表示来稍微削弱种子。
    • 与使用默认构造函数相比,随机性大大
    • @PeterLawrey 在这里你推荐使用'new SecureRandom()' 但在this 你说使用'System.nanoTime'。在this 情况下,我应该使用“new SecureRandom()”还是“System.nanoTime”。提前致谢
    猜你喜欢
    • 2010-11-30
    • 1970-01-01
    • 2018-03-29
    • 1970-01-01
    • 1970-01-01
    • 2017-12-28
    • 2012-01-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多