6

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

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

有人用过这个发电机吗?

编辑:要求是:

a) 具有统计独立性

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

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

d) 具有密码强度。

4

3 回答 3

3

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

于 2013-07-19T13:11:11.603 回答
3

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

例如,要洗一包纸牌,您只需要 226 位,但一个简单的算法(调用nextInt(n)每张牌)可能会使用 1600 或 3200 位,浪费了 85% 的熵,并使您更容易受到延迟的影响 7 倍。

对于这种情况,我认为雅克医生的方法是合适的。

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

用于缩放随机数生成器的位回收

我会倾向于有效使用而不是拉伸,因为我认为证明可靠熵流的有效消费者的公平性要比用种子良好的 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).

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

于 2013-07-19T15:20:40.437 回答
1

你可以使用java.security.SecureRandom,因为你可以使用java.util.Random这些东西。

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

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

于 2013-07-19T13:11:01.050 回答