TVP

# 问用window.crypto.getRandomValues在JavaScript中洗牌EN

Stack Overflow用户

0.000000000000000000000000000000000000000000000000000000005324900157 %

..。可能的排列。这意味着在理论上可以玩或模拟的所有可能的游戏实际上永远看不到。

• A正确的
1. 。由于我们是在确定性机器上，PRNG将是我们将得到的全部，也许这应该是CSPRNG。
2. 至少具有226位熵的随机种子。

1. Fisher-Yates shuffle将会很好，据我所知，
2. xorshift7 RNG的内部状态超过了所需的226位，并且如果
3. 我们可以生成所需的226位的熵来用作我们的种子。如果这还不够，我们可以添加更多的熵from other sources.

``````var randomBytes = generateRandomBytes(226);

function generateRandomBytes(n) {
var data = new Uint8Array(
Math.ceil(n / 8)
);
window.crypto.getRandomValues(data);

return data;
}``````

### 回答 3

#### Stack Overflow用户

``````function shuffledeck() {
var cards = Array("A♣️","2♣️","3♣️","4♣️","5♣️","6♣️","7♣️","8♣️","9♣️","10♣️","J♣️","Q♣️","K♣️",
"A♦️","2♦️","3♦️","4♦️","5♦️","6♦️","7♦️","8♦️","9♦️","10♦️","J♦️","Q♦️","K♦️",
"A♥️","2♥️","3♥️","4♥️","5♥️","6♥️","7♥️","8♥️","9♥️","10♥️","J♥️","Q♥️","K♥️",
"A♠️","2♠️","3♠️","4♠️","5♠️","6♠️","7♠️","8♠️","9♠️","10♠️","J♠️","Q♠️","K♠️");
var rndbytes = new Uint8Array(100);
var i, j, r=100, tmp, mask=0x3f;

/* Fisher-Yates shuffle, using uniform random values from window.crypto */
for (i=51; i>0; i--) {
if ((i & (i+1)) == 0) mask >>= 1;
do {
/* Fetch random values in 100-byte blocks. (We probably only need to do */
/* this once.) The `mask` variable extracts the required number of bits */
/* for efficient discarding of random numbers that are too large. */
if (r == 100) {
window.crypto.getRandomValues(rndbytes);
r = 0;
}
} while (j > i);

/* Swap cards[i] and cards[j] */
tmp = cards[i];
cards[i] = cards[j];
cards[j] = tmp;
}
return cards;
}``````

`window.crypto`库的评估确实值得提出自己的问题，但不管怎样...

`window.crypto.getRandomValues()`提供的伪随机流对于任何目的都应该是足够随机的，但在不同的浏览器中由不同的机制生成。根据2013 survey的说法

• Firefox (v. 21+)使用带有440位种子的NIST SP 800-90。注:该标准在2015年更新，删除了(可能是后置的) `Dual_EC_DRBG`椭圆曲线PRNG算法。

• Safari，Chrome和Opera使用带有1024位种子的ARC4流密码。

``````// Add Fisher-Yates shuffle method to Javascript's Array type, using
// window.crypto.getRandomValues as a source of randomness.

if (Uint8Array && window.crypto && window.crypto.getRandomValues) {
Array.prototype.shuffle = function() {
var n = this.length;

// If array has <2 items, there is nothing to do
if (n < 2) return this;
// Reject arrays with >= 2**31 items
if (n > 0x7fffffff) throw "ArrayTooLong";

var i, j, r=n*2, tmp, mask;
// Fetch (2*length) random values
var rnd_words = new Uint32Array(r);
// Create a mask to filter these values

// Perform Fisher-Yates shuffle
for (i=n-1; i>0; i--) {
if ((i & (i+1)) == 0) mask >>= 1;
do {
if (r == n*2) {
// Refresh random values if all used up
window.crypto.getRandomValues(rnd_words);
r = 0;
}
} while (j > i);
tmp = this[i];
this[i] = this[j];
this[j] = tmp;
}
return this;
}
} else throw "Unsupported";

// Example:
deck = [ "A♣️","2♣️","3♣️","4♣️","5♣️","6♣️","7♣️","8♣️","9♣️","10♣️","J♣️","Q♣️","K♣️",
"A♦️","2♦️","3♦️","4♦️","5♦️","6♦️","7♦️","8♦️","9♦️","10♦️","J♦️","Q♦️","K♦️",
"A♥️","2♥️","3♥️","4♥️","5♥️","6♥️","7♥️","8♥️","9♥️","10♥️","J♥️","Q♥️","K♥️",
"A♠️","2♠️","3♠️","4♠️","5♠️","6♠️","7♠️","8♠️","9♠️","10♠️","J♠️","Q♠️","K♠️"];

deck.shuffle();``````

#### Stack Overflow用户

``````// Fisher-Yates
function shuffle(array) {
var i, j;

for (i = array.length - 1; i > 0; i--) {
j = randomInt(0, i + 1);
swap(array, i, j);
}
}

// replacement for:
//     Math.floor(Math.random() * (max - min)) + min
function randomInt(min, max) {
var range = max - min;
var bytesNeeded = Math.ceil(Math.log2(range) / 8);
var randomBytes = new Uint8Array(bytesNeeded);
var maximumRange = Math.pow(Math.pow(2, 8), bytesNeeded);
var extendedRange = Math.floor(maximumRange / range) * range;
var i, randomInteger;

while (true) {
window.crypto.getRandomValues(randomBytes);
randomInteger = 0;

for (i = 0; i < bytesNeeded; i++) {
randomInteger <<= 8;
randomInteger += randomBytes[i];
}

if (randomInteger < extendedRange) {
randomInteger %= range;

return min + randomInteger;
}
}
}

function swap(array, first, second) {
var temp;

temp = array[first];
array[first] = array[second];
array[second] = temp;
}``````

#### Stack Overflow用户

https://stackoverflow.com/questions/47194034