如何使用crypto.getRandomValues中的随机数随机化数组?

时间:2013-08-20 08:45:13

标签: javascript jquery html5 random cryptography

我知道您可以使用Fisher-Yates Shuffle在JavaScript中对数组进行随机播放。然而,这使用Math.random作为随机数。我想知道你是否可以使用window.crypto.getRandomValues()为随机数源获得更好的 shuffle?

我有一个下面的工作。 getRandomIntInRange()函数使用rejection sampling和示例指定here

请告诉我这是否是正确的方法,或者如果您能想到更好的方法。 JSFiddle here

$(document).ready(function()
{
    var dataArray = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14'];               
    var shuffledArray = shuffleArray(dataArray);                

    console.log(shuffledArray);
});         

function getRandomIntInRange(min, max) {

    var range = max - min + 1;
    var maxRange = 256;
    var byteArray = new Uint8Array(1);

    // Fill byteArray with 1 random number
    window.crypto.getRandomValues(byteArray);

    // If outside of range, get another
    if (byteArray[0] >= Math.floor(maxRange / range) * range)
    {
        return getRandomIntInRange(min, max);
    }

    return min + (byteArray[0] % range);
}

function shuffleArray(dataArray) {

    var counter = dataArray.length, temp, index;

    while (counter > 0)
    {
        index = getRandomIntInRange(0, counter - 1);
        counter--;

        temp = dataArray[counter];
        dataArray[counter] = dataArray[index];
        dataArray[index] = temp;
    }

    return dataArray;
}

1 个答案:

答案 0 :(得分:3)

这段代码没有任何问题(虽然使用数字1到14的字符串似乎毫无意义地缓慢而复杂 - 只有数字1到14有什么问题?)。您当然可以自由使用您喜欢的任何RNG算法。但是,不同的算法被设计为最适合不同的任务。一般来说,为模拟而设计的RNG对于密码学来说是不安全的;加密安全的RNG可用于模拟,但可能太慢。如果你只想玩几款游戏,没问题。但是如果你想要模拟十亿只二十一点或扑克,或者蒙特卡罗与数十亿数据点的集成,那么使用加密RNG可能会使你的代码在几分钟内运行,几周内无法获益。