【问题标题】:Java SecureRandom declaration should be static class specific or can be instance specificJava SecureRandom 声明应该是特定于静态类的,也可以是特定于实例的
【发布时间】:2021-09-18 00:25:57
【问题描述】:

我正在尝试使用 SecureRandom 在我的 java 项目中生成随机数。但我有点困惑如何为SecureRandom 保留我的对象。它应该是static 类成员。我不打算从外面打电话给这个。以下是我目前的实现:

Class MyClass {

    private static final SecureRandom secureRandom = new SecureRandom();

    private long calculate(int noOfRetry){
        final long value = someValueCalculationWith-noOfRetry;
        final float randomNo = secureRandom().nextFloat() + 1;
        return (long) (value*randomNo);
    }
}

这是在 java 中使用 SecureRandom 的正确方法吗?

【问题讨论】:

  • 取决于上下文,请参阅此处了解一些非常好的信息重新熵问题stackoverflow.com/questions/27622625/…
  • 请注意 floatdouble 具有非常有趣的属性 w.r.t。精度、舍入和随机性。当我看到在安全应用程序中使用floatdouble 时,我总是感到有点不寒而栗——有些东西可能不合时宜。使用例如nextInt(int max) 代替。
  • 哦,这似乎是一个随机超时或其他什么,也要注意这可能会成功隐藏一个计算的计算时间,但统计数据仍然可以提供有趣的细节。例如。如果您将最小额外时间添加到最小运行时间,您会泄漏后者,即使对于该特定实例也是如此。有一个恒定时间的实现可能会更好地隐藏东西。

标签: java random cryptography


【解决方案1】:

我完全同意 Maartens 的回答。但是可以注意到 java.util 类为 SecureRandom 自身创建了静态。

public final class UUID implements java.io.Serializable, Comparable<UUID> {

    ...

    /*
     * The random number generator used by this class to create random
     * based UUIDs. In a holder class to defer initialization until needed.
     */
    private static class Holder {
        static final SecureRandom numberGenerator = new SecureRandom();
    }

【讨论】:

    【解决方案2】:

    不,不要这样做static。如果您愿意,可以将其设为实例字段,但将其设为类字段并不是最佳选择。例如。请参阅派生自 Random 类的线程安全说明:

    java.util.Random 的实例是线程安全的。但是,跨线程并发使用相同的java.util.Random 实例可能会遇到争用,从而导致性能下降。考虑在多线程设计中改用ThreadLocalRandom

    请注意,ThreadLocalRandom 在密码学上是安全的,因此对您来说不是一个好选择。一般来说,您应该尽量避免使用static 类字段,尤其是当实例是有状态的时。

    如果您只需要一个或几个不在紧密循环中的方法中的随机实例,那么将其设置为本地实例是非常好的(换句话说,只需使用var rng = new SecureRandom(),或者如果您只使用new SecureRandom()一个需要它的方法调用)。

    【讨论】:

    • 谢谢伙计……我明白了。所以在同一个方法中,我可以像这样多次调用 new SecureRandom() :final float randomNo = new SecureRandom().nextFloat() + 1;
    • 这里只是一个注释。根据此链接 SecureRandom 保证是线程安全的bugs.openjdk.java.net/browse/JDK-8165115 特别是似乎不需要同步对 nextFloat 的访问,唯一的同步方法与种子和生成字节数组有关。
    • 好吧,在同样的方法中,我只创建一个实例并使用一个变量。 SecureRandom 的初始化时间并不长,但是一次总比多次好。
    • @avd 当然,应该是这样,因为 - 作为子类 - 它需要遵守 Random 的规范。这就是为什么我引用了该类的 JavaDoc 的引用。看来,该实现仅允许SecureRandomSpi 依赖SecureRandom 来确保线程安全。也许一些外部提供者没有阅读Random 类文档:)
    • 我在您的文章中没有看到任何可以证明将静态使用描述为“危险”的内容。可能会很慢,但并不危险。
    猜你喜欢
    • 2013-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多