【问题标题】:Behaviour of SecureRandomSecureRandom 的行为
【发布时间】:2012-06-19 10:38:35
【问题描述】:

尽管关注了很多关于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 的任何额外好处,因为它几乎给出了相同的结果。

谁能告诉我我在这里做的是否正确?

【问题讨论】:

    标签: java algorithm security random cryptography


    【解决方案1】:

    您是对随机数的普遍误解的受害者:随机序列并不意味着一个数字不能在该序列中重复。恰恰相反,它必须具有很高的概率。这种误解实际上是用来区分人类产生的“随机”序列和真实序列。由人类生成的 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 在一个仁慈的环境中,您只需要良好的统计属性,但不关心可预测性(蒙特卡洛模拟、单人扑克与计算机、一般的计算机游戏) - 即没有钱可以赢或如果有人能够成功预测这些随机数,就会失去生命。

    【讨论】:

    • 非常感谢您提供如此详细的描述 :) 真的很有帮助。
    • 此外,CSPRNG 应该不受追溯:给定其输出的一部分,您无法追溯其先前的输出。它应该不受未来或过去的扩展攻击。
    【解决方案2】:

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

    【讨论】:

    • 好吧,根据我阅读的文章,我理解的是高质量的随机性很重要,它由 SecureRandom 提供。我认为这是唯一但至关重要的优势。
    • 正确。如果你需要它,你真的需要它。但是,如果您不需要它,您将无缘无故地付出计算成本。
    【解决方案3】:

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

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

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

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

    【讨论】:

    • 但这仍然是一个需要回答的问题。返回 2 的函数是随机函数。只是不是一个好人。 ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-21
    • 2017-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多