我們一直使用的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