在全面回顾之后,我得出结论,解决方案是正确的,是Durstenfeld shuffle的逐字实现。
然而,Durstenfeld/Fisher-Yates洗牌只是随机的,因为它是RNG来源。我的解决方案取决于
random-number-csprng
CSPRNG lib,使用
crypto.randomBytesAsync
,因此在大多数情况下都是加密安全的(请参阅
How random is crypto#randomBytes?
).
更新
:我在此处发布了此解决方案的功能等效但效率更高的版本
crypto-secure-shuffle
,也可作为npm包提供。以下是相关实施:
const secureRandomInRange = require("random-number-csprng");
async function secureShuffle(array) {
const promises = [];
for (let i = array.length - 1; i > 0; i--) {
promises.push(secureRandomInRange(0, i));
}
const randomNumbers = await Promise.all(promises);
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;
}