如何生成具有特定位范围的 SecureRandom 数

时间:2021-03-12 00:49:18

标签: java random bit secure-random

我有未位对齐的最大位数35 并且需要从 1 - 68719476734(35 位的最大数量)生成唯一的随机数。 可以使用 SecureRandom 但必须从中提取 5 个字节并转换为 Long 可能,但冲突的可能性似乎是一个问题。有哪些选项可以为该范围生成随机数。 如果在这个范围内发生碰撞并重新生成,我可以用 nanoTime 播种这个随机数吗?

2 个答案:

答案 0 :(得分:1)

首先,几点意见:

  • 35 位的最大值是 34359738367,而不是 68719476734。
    68719476734 甚至不是 36 位的最大值,68719476735 是。

  • 不要播种SecureRandom。这降低了它的安全性。

要生成一个35位的随机数,不包括零值,只需生成一个long随机值,取最后35位,如果值为零则重做。

SecureRandom r = new SecureRandom();

long value;
do {
    value = r.nextLong() & ((1L << 35) - 1);
} while (value == 0);

答案 1 :(得分:0)

可能有更好的方法,但也许这会有所帮助。第一个简单地打印从流生成的单个数字。第二个屏蔽掉所需的位。有趣的是,相同种子的值不同(我无法解释)。但是允许范围的第一种方法可能足以满足您的需求。我显然不是这方面的专家,但提供它是为了培养一些想法。

SecureRandom r = new SecureRandom();
 r.setSeed(23);
// generate a sum of 1 element to get the element from the stream.
long v = 0;
while (v == 0) {
   v = r.longs(1,1L<<34, (1L<<35)-1).sum();
}
System.out.println(v);
System.out.println(64-Long.numberOfLeadingZeros(v));

r.setSeed(23);
long vv = 0;
while (vv == 0) {
   vv = r.nextLong()&((1L<<35)-1);
}

System.out.println(vv);
System.out.println(64-Long.numberOfLeadingZeros(vv));

印刷品

31237208166
35
9741674490
34

我的假设是,如果随机数不满足安全要求,则不会提供上述流版本。