本文介绍了如何使用window.crypto.getRandomValues获取特定范围内的随机值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们一直在使用Math.random获取4000-64000之间的随机数。:

We had been using Math.random to get random numbers between 4000-64000.:

Math.floor(Math.random() * 60000 + 4000);

我们现在必须用更加加密的安全随机数生成器替换它。在搜索了这个问题之后,我们决定使用
window.crypto.getRandomValues。我无法弄清楚如何使用它来获取特定范围之间的随机数。有人可以帮忙吗。

We have to now replace this with a more cryptographically secure random number generator. After searching on this issue we have decided to go with window.crypto.getRandomValues. I am not able to figure out how to use this to get a random number between a particular range. Can someone please help out.

推荐答案

对于给定的最小值和最大值,公式描述你要多少位平均使用如果您一次请求 u 位并重试,如果返回结果会引入偏差。

For a given min and max, the formula describes how many bits you'll use on average if you request u bits at once and retry if returning the result would introduce bias.

幸运的是,最佳策略是一次性请求 ceil(log2(max-min + 1))位。我们只能用 crypto.getRandomValues 来获取完整的字节,所以如果我们每个函数有一次 crypto.getRandomValues 的调用打电话,我们能做的最好的事情是:

Fortunately, the optimal strategy is simply requesting ceil(log2(max - min + 1)) bits at once. We can only get full bytes with crypto.getRandomValues anyways, so if we have one call of crypto.getRandomValues per function call, the best we can do is:

// Generate a random integer r with equal chance in  min <= r < max.
function randrange(min, max) {
    var range = max - min;
    if (range <= 0) {
        throw new Exception('max must be larger than min');
    }
    var requestBytes = Math.ceil(Math.log2(range) / 8);
    if (!requestBytes) { // No randomness required
        return min;
    }
    var maxNum = Math.pow(256, requestBytes);
    var ar = new Uint8Array(requestBytes);

    while (true) {
        window.crypto.getRandomValues(ar);

        var val = 0;
        for (var i = 0;i < requestBytes;i++) {
            val = (val << 8) + ar[i];
        }

        if (val < maxNum - maxNum % range) {
            return min + (val % range);
        }
    }
}

如果生成多个值,您可以考虑一些优化,即提前请求更多字节(即更大的数组)。如果你的范围变得更小(比如想要翻转硬币),那么以基于位的方式工作也许是有益的,即先前请求许多位然后只用掉你真正需要的随机位。

If you generate many values, you may consider some optimizations, namely requesting more bytes (i.e. a larger array) in advance. If your range becomes smaller (say you want to flip a coin), than it may also be beneficial to work in a bit-based manner, i.e. request many bits upfront and then only use up the random bits you really need.

这篇关于如何使用window.crypto.getRandomValues获取特定范围内的随机值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 18:01