【发布时间】:2020-02-01 13:33:24
【问题描述】:
我有一个需要长随机位序列的应用程序。
因为我依赖这些序列是“真正随机的”,所以我想使用 SecureRandom。
遗憾的是,我需要每个这样的序列两次。
我无法将它们保存在 RAM 中,因为它们太长了。
我不想将它们写入硬盘驱动器,因为写入和读取硬盘驱动器会耗费时间和硬盘驱动器空间,并使代码变得不必要地复杂。
但是,由于某些生成器生成的“随机”位序列确定性地取决于生成器在创建时所处的状态,因此(也许)可以保存并重新创建新生成的 SecureRandom 对象所处的状态,允许重新创建位序列。
主要问题是:
(如何)你能保存 SecureRandom 随机数生成器的整个状态吗?克隆够吗? (可能有一些操作系统状态也起作用,例如,当前时间)您是否可以克隆任何其他强 RNG,以便原始和克隆创建相同的输出?
另外,我感兴趣的是普通随机数生成器会创建什么样的模式,使它们不安全,以及是否可以如上所述保存和恢复它们的状态。
编辑:
我为此创建了一个 LCG。
但是,我认为它不能正常工作。
它会创建一个“强”的伪随机位序列吗?
当它连续多次产生相同的值时,它变得可疑。 例如:
假的 错误的 真的 真的 真的 真的 错误的 真的 错误的 错误的 错误的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的 真的
public class DeterministicRandom{
private BigInteger state;
private BigInteger a;
private BigInteger c;
private static final int o=32;
private static final BigInteger m=BigInteger.ONE.shiftLeft(o*8);
public DeterministicRandom(){
a=RandomUtils.randomBigInt(o);
c=RandomUtils.randomBigInt(o);
state=RandomUtils.randomBigInt(o);
}
public DeterministicRandom(DeterministicRandom r){
a=r.a;
c=r.c;
state=r.state;
}
public boolean nextBoolean(){
boolean r=state.testBit(o*8-7);
state=state.multiply(a).add(c).mod(m);
return r;
}
}
public class RandomUtils {
private static Random random = new Random();
public static byte[] nextBytes(byte[] d){
random.nextBytes(d);
return d;
}
public boolean randomBit(){
return random.nextBoolean();
}
public static BigInteger randomBigInt(int bytes){
byte[] d=new byte[bytes+1];
random.nextBytes(d);
d[0]=0;
BigInteger x=new BigInteger(d);
return x;
}
}
【问题讨论】:
-
一种方法是使用
SecureRandom生成种子,然后使用该种子创建两个常规Random实例。 -
那么,随机“随机”就够了吗?随机是“确定性的”吗? “种子生成:随机使用系统时钟作为种子/或生成种子。”-geeksforgeeks.org/random-vs-secure-random-numbers-java上述问题的答案是否取决于实现?我真的必须确保序列完全按照第一次生成的方式重新生成。
-
SecureRandom生成真正的随机种子。如果你用它来播种你的两个Random实例,它们将产生相同的伪随机确定性序列。如果您想要巨大的真正随机序列,生成它们可能比从磁盘读取它们要慢,因为收集熵数据往往很慢。您请求的所有信息都在 JavaDoc 及其引用的规范中。 -
你不能同时拥有。真正的随机性与确定性截然相反。
-
你想要的叫做伪随机数生成器,Java already has one built in。除非您可以在数学上证明您需要 更好 随机数序列生成,否则您根本不需要 SecureRandom。只需使用 Random,只有当您确实有证据不够好时,才开始寻找更好的 PRNG。