【问题标题】:How to generate a SecureRandom number with a specific bit range [duplicate]如何生成具有特定位范围的 SecureRandom 数 [重复]
【发布时间】:2021-03-12 00:49:18
【问题描述】:

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

【问题讨论】:

  • 您所说的“碰撞几率似乎令人担忧”是什么意思?对于真正的随机值,总是有可能发生冲突,对此您无需采取任何措施。如果你消除了碰撞的机会,结果将不是真正的随机。
  • 寻找一个足够随机的种子,以避免任何随机数的冲突
  • 为什么你认为 nanoTime 会比 SecureRandom 类中内置的任何算法产生更好的随机性?
  • 如果它可以用于 SecureRandom,我正在寻找种子。在这种情况下如何使用 SecureRandom 确保没有种子的范围

标签: java random bit secure-random


【解决方案1】:

首先,几个cmets:

  • 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);

【讨论】:

    【解决方案2】:

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

    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
    

    我在这里的假设是,如果随机数不符合安全要求,则不会提供上述流版本。

    【讨论】:

    • 这个答案完全忽略了问题中下限为1而不是0的部分。
    猜你喜欢
    • 1970-01-01
    • 2020-03-01
    • 2015-10-28
    • 2014-10-23
    • 1970-01-01
    • 2020-10-16
    • 2018-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多