8

尽管在阅读了很多关于 的文章后,我还是对 JavaSecureRandom中 Security API 的使用遇到了疑问。SecureRandom在下面的例子中。

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");
        }
    }
}

}

当我运行这个程序时,我没有发现使用 a 的任何额外好处,SecureRandom因为它几乎给出了相同的结果。

谁能让我知道我在这里做的事情是否正确?

4

3 回答 3

17

一般来说,您是对随机数的普遍误解的受害者:随机序列并不意味着一个数字不能在该序列中重复。恰恰相反,它必须具有很高的概率。这种误解实际上是用来区分人类产生的“随机”序列和真实序列。由人类生成的 0 和 1 的“随机”序列可能如下所示:

0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, ....

而一个真正的随机序列并不羞于重复相同的数字两次以上:) 一个很好的例子是统计测试也寻找重复。

两种生成器都具有良好的“统计特性”

这也是一种常见的误解,即加密安全的随机数会以某种方式产生“更多随机”的值。它们的统计概率可能非常相似,并且在这些标准统计测试中都表现得非常好。

在哪里使用哪个

所以这实际上取决于你想要做什么,你的选择应该是 PRNG 还是加密安全 PRNG (CSPRNG)。“正常”PRNG 非常适合模拟目的,例如蒙特卡洛方法等。CSPRNG 的额外好处是不可预测性。因为 CSPRNG 可以“做更多”的机会很高,所以它的性能也会比普通 PRNG 差。

可以看出,“安全”PRNG 的概念与预测其输出的下一位的能力紧密相关。对于 CSPRNG,在任何时候预测其输出的下一位在计算上是不可行的。当然,这仅在您将其种子值视为秘密时才成立。一旦有人找到了种子,整个事情就变得很容易预测——只需重新计算已经由 CSPRNG 算法生成的值,然后计算下一个值。可以进一步表明,不受“下一位预测”的影响实际上意味着没有任何统计测试可以区分 CSPRNG 的分布与真正的随机均匀分布的分布。所以 PRNG 和 CSPRNG 之间还有另一个区别:虽然好的 PRNG 在许多统计测试中表现良好,所有测试。

经验法则在哪里使用

  • 您在“敌对”环境中使用 CSPRNG,您不希望外部人员能够猜测敏感信息(会话 ID、赢/输真钱的在线扑克……)
  • 而 PRNG 在一个仁慈的环境中,您只需要良好的统计属性,但不关心可预测性(蒙特卡洛模拟,单人扑克与电脑,一般的电脑游戏) - 即没有钱可以赢得或生命将是如果有人能够成功预测这些随机数,就会丢失。
于 2012-06-19T12:53:58.557 回答
5

安全和不安全算法通常会给出几乎相同的结果。您无法在输出中检测到安全漏洞。带有不可撬锁的门和带有可以轻松撬开的锁的门看起来几乎相同,如果您只需转动把手,它们都不会打开。这就是编写安全代码和处理诸如加密和身份验证之类的事情是使用专门技术进行设计、开发,特别是测试的编程领域的原因之一。

于 2012-06-19T10:45:12.190 回答
2

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

让我们以骰子为例。使用安全随机就像使用普通的未加载骰子。每一次掷骰子都独立于前一次掷骰子。不安全的随机数使用前一次掷骰子来确定下一个结果。(因此,如果您知道之前的掷骰是 6,则可以预测下一次掷骰)。

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

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

于 2012-06-19T10:55:18.907 回答