出于基准测试的目的,我想让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());
}
}
对我来说,即使指定了种子,上述程序也会产生不同的值。
答案 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)。