从SecureRandom获取确定性值?

时间:2014-12-07 09:24:30

标签: java random

出于基准测试的目的,我想让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());
    }
}

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

3 个答案:

答案 0 :(得分:6)

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

答案 1 :(得分:3)

为了覆盖默认种子,请像这样传递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

答案 2 :(得分:1)

documentation中明确解释了一切:

  

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

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

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

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