尽管在SecureRandom
上关注了很多文章之后,我在Java中使用SecureRandom
安全API时遇到了疑问。在下面的例子中。
public class SecureRandomNumber {
public static void main(String[] args) throws NoSuchAlgorithmException {
TreeSet<Integer> secure = new TreeSet<Integer>();
TreeSet<Integer> unSecure = new TreeSet<Integer>();
SecureRandom sr = new SecureRandom();
byte[] sbuf = sr.generateSeed(8);
ByteBuffer bb = ByteBuffer.wrap(sbuf);
long d = bb.getLong();
sr.setSeed(d);
Random r = new Random();
r.setSeed(System.nanoTime());
for (int k = 0; k < 99999; k++) {
int i = sr.nextInt();
if (!secure.add(i)) {
System.out.println("Repeated Secure Random Number");
} else {
// System.out.println("************Unique***********");
}
int j = r.nextInt();
if (!unSecure.add(j)) {
System.out.println("Repeated UnSecure Random Number");
}
}
}
}
当我运行此程序时,我发现使用SecureRandom
没有任何额外的好处,因为它几乎给出了相同的结果。
如果我在这里做正确的事,有人能告诉我吗?
答案 0 :(得分:17)
一般来说,你是对随机数的常见误解的受害者:随机序列并不意味着数字不能在该序列中重复。恰恰相反,它具有很高的概率。这种误解实际上用于说明人类从真实的序列中产生的“随机”序列。人类生成的0和1的“随机”序列可能如下所示:
0,1,0,1,1,0,1,0,0,1,0,1,0 ...... ....
虽然真正的随机序列并不害怕重复相同的数字超过两次:)一个很好的例子是statistical tests也寻找重复。
这也是一个常见的误解,加密安全随机数会以某种方式产生“更随机”的值。他们的统计概率可能非常相似,并且在这些标准统计检验中都表现得非常好。
因此,无论您选择的是PRNG还是加密安全的PRNG(CSPRNG),它实际上取决于您想要做什么。 “正常”PRNG完全可以用于模拟目的,例如蒙特卡罗方法等.CSPRNG的额外好处将使您具有不可预测性。因为CSPRNG可以“做得更多”的机会很高,其性能也会比香草PRNG的性能更差。
可以证明,“安全”PRNG的概念与预测其输出的下一位的能力紧密耦合。对于CSPRNG,在任何时候预测其输出的下一位在计算上是不可行的。只有当你将其种子价值视为秘密时,这才有效。一旦有人发现了种子,整个事情就变得容易预测 - 只需重新计算CSPRNG算法已经生成的值,然后计算下一个值。可以进一步证明,对“下一位预测”免疫实际上意味着没有任何统计测试可以区分CSPRNG的分布与真实随机均匀分布的分布。因此,PRNG和CSPRNG之间存在另一个区别:虽然良好的PRNG在许多统计测试中表现良好,但CSPRNG保证在所有测试中表现良好。
经验法则在哪里使用
答案 1 :(得分:5)
安全和不安全的算法经常会给几乎相同的结果。您无法检测输出中的安全漏洞。一扇带有不可拆卸锁的门和一把带锁的门可以琐碎地采摘,看起来几乎一样,如果你只是转动手柄也不会打开。这是编写安全代码和处理加密和身份验证之类的事情的原因之一,这是使用专门的设计,开发,特别是测试技术进行编程的一个领域。
答案 2 :(得分:2)
SecureRandom每次都不能确保唯一的随机数。它只是确保给定以前的数字,您无法预测下一个随机数。所以,基本上,你正在寻找错误的答案。
让我们使用骰子的例子。使用安全随机就像使用普通的卸载骰子。每个骰子卷都独立于之前的骰子卷。不安全的随机使用前一个骰子滚动来确定下一个结果。 (所以如果你知道前面的掷骰是6,你可以预测下一个掷骰子。)
因此,如果用户/黑客/管理员/等可以预测如果给出之前的随机数列表,那么您基本上必须确定它是否对您的应用程序有问题。 (在大多数情况下,这将是一个问题)。如果您只是想使用随机数来选择要在网页中显示的随机数,那么正常随机就可以了。如果您想使用随机数进行安全性,游戏或交易,最好使用SecureRandom。
我不确定,但我认为使用SecureRandom会增加非常小的开销。所以随机稍快一点。但是在大多数情况下,当人们滥用不安全的随机数生成器的不安全性时,速度的提高并不值得潜在的问题。