【问题标题】:Get deterministic values from SecureRandom?从 SecureRandom 获取确定性值?
【发布时间】:2014-12-07 09:24:29
【问题描述】:

出于基准测试的目的,我希望 SecureRandom 产生确定性输出。这是否可以通过使用种子(或者可能是算法规范)来实现?

import java.security.SecureRandom;
class TestSecureRandom {
    public static void main(String [] args) {
        SecureRandom rnd = new SecureRandom();
        rnd.setSeed(1);
        System.out.println(rnd.nextInt());
    }
}

对我来说,即使指定了种子,上述程序也会产生不同的值。

【问题讨论】:

  • 根据其 javadoc (docs.oracle.com/javase/7/docs/api/java/security/…),它是不确定的。 setSeed 只会改变它的内部状态,但它仍然是不确定的。
  • 必须是SecureRandom吗?可以是其他类型的Random(例如Random 本身)吗?
  • 没有。编程到interface。在代码中使用Random

标签: java random


【解决方案1】:

这样做的最简单方法可能是让大部分代码仅依赖于Random,并注入一个实例(例如,通过将其传递给构造函数)。这样,出于测试目的,您可以传入带有固定种子的简单 Random - 但是对于需要安全性的真实运行,您可以传入 SecureRandom 的实例。

【讨论】:

    【解决方案2】:

    为了覆盖默认种子,像这样传递PRNG算法名称

    import java.io.UnsupportedEncodingException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    class TestSecureRandom {
        public static void main(String [] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
            SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
            rnd.setSeed("foo".getBytes("us-ascii"));
            System.out.println(rnd.nextInt());
            System.out.println(rnd.nextInt());
        }
    }
    

    输出

    -207444710
    -1693504542
    

    【讨论】:

    • 我最终使用了Random 接口,但这也很有用。
    【解决方案3】:

    documentation中的一切都解释得很清楚:

    许多 SecureRandom 实现都是伪随机的形式 数字生成器 (PRNG),这意味着它们使用确定性 算法从真正的随机种子产生伪随机序列。 其他实现可能会产生真正的随机数,还有其他的 可以结合使用这两种技术。

    如果您询问实现,在 Linux 中它使用/dev/urandom,因此结果是不可预测的。但是,您可以强制SecureRandom 使用另一种算法:

    SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
    

    但在很多情况下,最合理的想法是使用一些 OOP 模式(例如,jon-skeet's answer)。

    【讨论】:

      猜你喜欢
      • 2023-04-06
      • 1970-01-01
      • 2017-12-04
      • 1970-01-01
      • 2018-11-04
      • 1970-01-01
      • 2011-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多