【问题标题】:Is java.secure.random a sufficient choice for gambling industry?java.secure.random 是赌博行业的充分选择吗?
【发布时间】:2015-01-02 17:48:02
【问题描述】:

Java 在 java.secure.random 包中提供了一个加密安全的随机数生成器。

如果我考虑 RNG 的播种和循环重新实例化等问题,是否可以使用此数字生成器?或者我可以“按原样”使用数字生成器吗?

有人使用过这个生成器吗?

编辑:要求是:

a) 具有统计独立性

b) 在其范围内公平分布(在统计预期范围内)

c) 通过各种公认的统计测试

d) 具有强大的加密能力。

【问题讨论】:

  • 进一步探索这个问题,我注意到最后的 SecureRandom 生成器是 SHA1。他们可能正在做一些显而易见的事情。否则 SHA1 的内部状态为 160 位,这不足以洗牌一副牌。这意味着无论您对 RNG 或 shuffle 算法做了什么,它仍然仅限于产生可能的排列的一个子集。严格来说,这并不是您的要求之一;所以也许没关系。

标签: java algorithm random prng


【解决方案1】:

正如其他人所说,安全 RNG 的吞吐量可能有限。为了减轻这种情况 您可以通过播种 CPRNG 来拉伸确保随机性,或者您可以 尝试优化您对比特流的使用。

例如,要洗一包纸牌,您只需要 226 位,但很幼稚 算法(为每张卡调用 nextInt(n))可能会使用 1600 或 3200 比特,浪费了你 85% 的熵,让你更容易受到影响 7 倍 延迟。

对于这种情况,我认为Doctor Jacques method 是合适的。

为此,这里有一些性能分析,逐步针对更多 昂贵的熵源(也包含代码):

Bit recycling for scaling random number generators

我会倾向于高效使用而不是拉伸,因为我认为 证明一个有效消费者的公平性会容易得多 可信赖的熵流,比证明任何绘图方法的公平性 具有良好种子的 PRNG。


编辑2 我不太懂 Java,但我把这些放在一起:

public class MySecureRandom extends java.security.SecureRandom {
    private long m = 1;
    private long r = 0;

    @Override
    public final int nextInt(int n) {
        while (true) {
            if (m < 0x80000000L) {
                m <<= 32;
                r <<= 32;
                r += (long)next(32) - Integer.MIN_VALUE;
            }
            long q = m / n;
            if (r < n * q) {
                int x = (int)(r % n);
                m = q;
                r /= n;
                return x;
            }
            m -= n * q;
            r -= n * q;
        }
    }
}

这取消了贪婪的默认统一 [0,n-1] 生成器,并用修改后的雅克博士版本替换它。对洗牌范围的值进行计时显示比SecureRandom.nextInt(n) 快了近 6 倍。

我之前版本的这段代码(只有 2 倍的加速)假设 SecureRandom.next(b) 是有效的,但事实证明调用是丢弃熵并将整个循环拖下。此版本管理自己的分块。

【讨论】:

【解决方案2】:

Documentation about SecureRandom 说它可能会阻止等待系统生成更多熵(例如,在 Linux 中它从 /dev/random 获取随机数),所以如果你要使用它,也许你需要一些帮助从硬件:安装随机数生成器卡(一种生成真实随机数的硬件设备,而不是伪随机数),这样您的系统将以足够的速度生成随机数,因此您的程序不会被阻塞。

【讨论】:

  • +1 您可以选择不同的 SecureRandom 策略,有些使用种子,有些不使用。
【解决方案3】:

您可以使用java.security.SecureRandom,就像您可以使用java.util.Random 一样。

请注意,java.security.SecureRandom 可能依赖于运行程序的计算机的一些熵。如果您从中获得许多随机值,那么它可能会阻塞,直到计算机生成足够的熵(例如,在 linux 上 java.security.SecureRandom 正在使用 /dev/urandom)。

因此,如果您想生成许多随机值并且可以使用 PRNG,请使用 java.util.Random

【讨论】:

  • 感谢您的回答。我刚刚用要求更新了问题。不幸的是,PRNG 是不够的。
猜你喜欢
  • 1970-01-01
  • 2018-07-04
  • 2021-06-02
  • 1970-01-01
  • 2012-05-06
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 2010-09-15
相关资源
最近更新 更多