Java在java.secure.random包中提供了一个加密安全的随机数生成器。
如果我考虑像播种和循环重新实例化RNG这样的事情,是否可以使用这个数字生成器?或者我可以按原样使用数字生成器吗?
有没有人使用过这台发电机?
编辑:要求是:
a)统计独立
b)在其范围内公平分配(在统计预期范围内)
c)通过各种公认的统计测试
d)加密强大。
答案 0 :(得分:3)
Documentation about SecureRandom说它可能阻止等待系统产生更多的熵(例如,在Linux中它从/ dev / random中获取随机数),所以如果你打算使用它,也许你需要它硬件的一些帮助:安装随机数生成器卡(一个生成真正随机数的硬件设备,而不是伪随机数),这样你的系统就会产生足够速度的随机数,这样你的程序就不会被阻塞。
答案 1 :(得分:3)
正如其他人所说,安全RNG的吞吐量有限。为了缓解这种情况 您可以通过播种CPRNG来扩展安全随机性,或者您可以 尝试优化比特流的使用。
例如,要改变一包卡片,你只需要226位,但这是一个天真的
算法(每张卡调用nextInt(n)
)可能会使用1600或3200
比特,浪费85%的熵,使你容易受到七倍的影响
延迟。
对于这种情况,我认为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]生成器,并将其替换为修改后的Doctor Jacques版本。定时卡片随机播放的值范围几乎比SecureRandom.nextInt(n)
快6倍。
我之前的此代码版本(仅加速2倍)假设SecureRandom.next(b)
效率很高,但事实证明,调用正在丢弃熵并将整个循环向下拖动。这个版本管理自己的分块。
答案 2 :(得分:1)
您可以使用java.security.SecureRandom
,因为您可以使用java.util.Random
进行此类操作。
请注意,java.security.SecureRandom
可能依赖于运行该程序的计算机的某些熵。如果您从中获取了许多随机值,那么它可能会阻塞,直到计算机生成足够的熵(例如,在Linux java.security.SecureRandom
上使用/dev/urandom
)。
因此,如果您想要生成许多随机值,并且使用PRNG可以使用java.util.Random
。