我们一直使用的Math.random得到4000-64000之间:如何使用window.crypto.getRandomValues获得特定范围内的随机值
Math.floor(Math.random() * 60000 + 4000);
我们必须现在替换这个随机数一个更加密码安全的随机数发生器。在搜索这个问题后,我们决定使用 window.crypto.getRandomValues。我无法弄清楚如何使用它来获得特定范围内的随机数。有人可以帮忙吗?
我们一直使用的Math.random得到4000-64000之间:如何使用window.crypto.getRandomValues获得特定范围内的随机值
Math.floor(Math.random() * 60000 + 4000);
我们必须现在替换这个随机数一个更加密码安全的随机数发生器。在搜索这个问题后,我们决定使用 window.crypto.getRandomValues。我无法弄清楚如何使用它来获得特定范围内的随机数。有人可以帮忙吗?
对于给定的最小值和最大值,公式描述了如果一次请求u
位,平均使用多少位,如果返回结果会导致偏差,则重试。
幸运的是,最佳策略是简单地请求ceil(log2(max - min + 1))
位。我们只能得到充分字节与crypto.getRandomValues
反正,所以如果我们有每个函数调用的crypto.getRandomValues
一个电话,我们能做的最好的是:
// 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);
}
}
}
如果产生许多值,你可以考虑一些优化,即请求提前多个字节(即更大的数组)。如果你的范围变小(比如说你想翻转一个硬币),那么比以比特为基础的方式工作也是有益的,例如,先前请求多个比特,然后只用尽你需要的随机比特。
另请参阅http://dimitri.xyz/random-ints-from-random-bits/和https://crypto.stackexchange.com/questions/8826/map-bytes-to-number和https:// crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-random-octet-string – caw