加密安全数组随机播放
Cryptographically secure array shuffle
我正在尝试使用加密安全的熵源对数组进行洗牌。
我在此处 How to randomize (shuffle) a JavaScript array? 发现了一个关于改组数组的类似问题。然而,几乎所有解决方案都使用 Math.random
,这是不安全的。
不幸的是,我在这个问题上没有 comment/post 的声誉。
这是我想出的解决方案,它使用 Durstenfeld 混洗与 CSPRNG 配对来生成给定范围内的随机整数(由 random-number-csprng 库提供)。
const randomNumber = require("random-number-csprng");
async function secureShuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = await randomNumber(0, i);
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
这个实现是否正确且没有偏见?
备注:
- 为了我的目的,数组最多包含 ~100 个元素
- 运行 nodejs v6.10.3 LTS(转译)
经过广泛审查后,我得出的结论是该解决方案是正确的,是 Durstenfeld 洗牌的逐字实施。
但是,Durstenfeld / Fisher-Yates 洗牌的随机性取决于它的 RNG 来源。我的解决方案取决于 random-number-csprng CSPRNG lib, which uses crypto.randomBytesAsync
, and is therefore cryptographically secure for most all purposes (see ).
更新:我在此处 crypto-secure-shuffle 发布了此解决方案的功能等效但更高效的版本,也可作为 npm 包使用。下面是相关的实现:
const secureRandomInRange = require("random-number-csprng");
async function secureShuffle(array) {
const promises = [];
// asynchronously generate an array of random numbers using a CSPRNG
for (let i = array.length - 1; i > 0; i--) {
promises.push(secureRandomInRange(0, i));
}
const randomNumbers = await Promise.all(promises);
// apply durstenfeld shuffle with previously generated random numbers
for (let i = array.length - 1; i > 0; i--) {
const j = randomNumbers[array.length - i - 1];
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
我正在尝试使用加密安全的熵源对数组进行洗牌。
我在此处 How to randomize (shuffle) a JavaScript array? 发现了一个关于改组数组的类似问题。然而,几乎所有解决方案都使用 Math.random
,这是不安全的。
不幸的是,我在这个问题上没有 comment/post 的声誉。
这是我想出的解决方案,它使用 Durstenfeld 混洗与 CSPRNG 配对来生成给定范围内的随机整数(由 random-number-csprng 库提供)。
const randomNumber = require("random-number-csprng");
async function secureShuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = await randomNumber(0, i);
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
这个实现是否正确且没有偏见?
备注:
- 为了我的目的,数组最多包含 ~100 个元素
- 运行 nodejs v6.10.3 LTS(转译)
经过广泛审查后,我得出的结论是该解决方案是正确的,是 Durstenfeld 洗牌的逐字实施。
但是,Durstenfeld / Fisher-Yates 洗牌的随机性取决于它的 RNG 来源。我的解决方案取决于 random-number-csprng CSPRNG lib, which uses crypto.randomBytesAsync
, and is therefore cryptographically secure for most all purposes (see
更新:我在此处 crypto-secure-shuffle 发布了此解决方案的功能等效但更高效的版本,也可作为 npm 包使用。下面是相关的实现:
const secureRandomInRange = require("random-number-csprng");
async function secureShuffle(array) {
const promises = [];
// asynchronously generate an array of random numbers using a CSPRNG
for (let i = array.length - 1; i > 0; i--) {
promises.push(secureRandomInRange(0, i));
}
const randomNumbers = await Promise.all(promises);
// apply durstenfeld shuffle with previously generated random numbers
for (let i = array.length - 1; i > 0; i--) {
const j = randomNumbers[array.length - i - 1];
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}