关于random:Java SecureRandom内部状态

Java SecureRandom internal state

我正在尝试按照下面的顺序对整数数组进行无序排列,

从http://en.wikipedia.org/wiki/fisher-yates-shuffle,

"当fisher-yates shuffle与伪随机数生成器或prng一起使用时,会出现另一个问题:由于此类生成器输出的数字序列完全由序列开始时的内部状态决定,因此由此类生成器驱动的shuffle可能不会产生比生成器更明显的排列。"具有不同的可能状态。……"

  • 如果我在SecureRandom生成器中植入大量字节,这就足够了吗?
  • 填充种子字节数组最简单的方法是什么?即

    字节[]种子=新字节[2048];//用随机的东西填充种子字节,最简单的方法是什么?SecureRandom SecureRandom=新SecureRandom(种子);

  • 代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    /**
     * http://en.wikipedia.org/wiki/Fisher-Yates_shuffle
     *
     * To shuffle an array a of n elements (indices 0..n-1):
     *      for i from n ? 1 downto 1 do
     *          j ← random integer with 0 ≤ j ≤ i
     *          exchange a[j] and a[i]
     */

    public int[] shuffle (int[] inSet ) {

        int [] returnSet = Arrays.copyOf(inSet, inSet.length);

        for( int i = inSet.length-1; i > 0; i-- ) {

            // j ← random integer with 0 ≤ j ≤ i
            int j = secureRandom.nextInt(i+1);

            // swap returnSet[i] and returnSet[j]
            int temp = returnSet[i];
            returnSet[i] = returnSet[j];
            returnSet[j] = temp;
        }
        return returnSet;
    }


    这是一篇很好的文章:"Java程序员的随机数指南"

    基本上,a)你不想使用java.util.Random,因为它表现出周期性行为(不好的随机性),b)SecureRandom是比java.util.Random大的改进,但根据你想洗牌的元素数量,它提供的自由度可能太小(详见本节)。另外一个问题是,SecureRandom的速度相当慢。如果您有性能问题,可以通过上面的链接找到比SecureRandom更快的备用prng。


    我认为数组的大小不如其内容重要。一个常见的做法是在当前时间创建种子。您还可以要求用户(如果可能)应用一些随机键盘或鼠标输入。我在密码管理器中注意到了这种技术。

    一切都取决于你的需要。我敢打赌,非常明智的方法是采用System.CurrentTimeMillis()(也可以通过多次加入或散列来使用它)。