关于java:SecureRandom的行为

Behaviour of SecureRandom

尽管在EDOCX1的0篇文章后面有很多文章,但是在Java中使用EDCOX1和0的安全API遇到了一个疑问。在下面的示例中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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和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在所有测试中都能很好地执行。

经验法则在哪里使用,那就是

  • 您在"敌对"环境中使用CSPRNG,您不希望外部人员能够猜测敏感信息(会话ID、在线扑克,其中真正的钱是赢/输…)。
  • 在一个仁慈的环境中,你只需要好的统计属性,但不关心可预测性(蒙特卡洛模拟,单人扑克对电脑,一般的电脑游戏),也就是说,如果有人能够成功预测这些随机数,就不会有钱赢,也不会有生命损失。


安全和不安全的算法通常会给出几乎相同的结果。您无法检测输出中的安全缺陷。一扇门有一把不可撬开的锁,一扇门有一把可以轻而易举地撬开的锁,看起来几乎是一样的,如果你转动把手,两扇门都不会打开。这就是为什么编写安全代码和处理诸如加密和身份验证之类的事情是一个使用专门技术进行设计、开发、特别是测试的编程领域的原因之一。


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

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

因此,如果用户/黑客/管理员等能够预测出之前的随机数字列表中出现的数字,那么您基本上必须确定应用程序是否存在问题。(在大多数情况下,这将是一个问题)。如果你只想用随机数来选择一个随机的东西在网页上显示,正常随机数是可以的。如果你想使用随机数进行证券交易,或者游戏交易,最好使用SecureRandom。

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