SecureRandom的行为

时间:2012-06-19 10:38:35

标签: java algorithm security random cryptography

尽管在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没有任何额外的好处,因为它几乎给出了相同的结果。

如果我在这里做正确的事,有人能告诉我吗?

3 个答案:

答案 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保证在所有测试中表现良好。

经验法则在哪里使用

  • 您在“敌对”环境中使用CSPRNG,在此环境中您不希望外部人员能够猜出敏感信息(会话ID,在线扑克赢得/丢失真金白银......)。
  • 并且PRNG处于一个仁慈的环境中,你只需要良好的统计属性但不关心可预测性(蒙特卡罗模拟,单人扑克与电脑,一般电脑游戏) - 即无法获得金钱或如果有人能够成功地预测这些随机数,那么生命将会丧失。

答案 1 :(得分:5)

安全和不安全的算法经常会给几乎相同的结果。您无法检测输出中的安全漏洞。一扇带有不可拆卸锁的门和一把带锁的门可以琐碎地采摘,看起来几乎一样,如果你只是转动手柄也不会打开。这是编写安全代码和处理加密和身份验证之类的事情的原因之一,这是使用专门的设计,开发,特别是测试技术进行编程的一个领域。

答案 2 :(得分:2)

SecureRandom每次都不能确保唯一的随机数。它只是确保给定以前的数字,您无法预测下一个随机数。所以,基本上,你正在寻找错误的答案。

让我们使用骰子的例子。使用安全随机就像使用普通的卸载骰子。每个骰子卷都独立于之前的骰子卷。不安全的随机使用前一个骰子滚动来确定下一个结果。 (所以如果你知道前面的掷骰是6,你可以预测下一个掷骰子。)

因此,如果用户/黑客/管理员/等可以预测如果给出之前的随机数列表,那么您基本上必须确定它是否对您的应用程序有问题。 (在大多数情况下,这将是一个问题)。如果您只是想使用随机数来选择要在网页中显示的随机数,那么正常随机就可以了。如果您想使用随机数进行安全性,游戏或交易,最好使用SecureRandom。

我不确定,但我认为使用SecureRandom会增加非常小的开销。所以随机稍快一点。但是在大多数情况下,当人们滥用不安全的随机数生成器的不安全性时,速度的提高并不值得潜在的问题。