From e157c32f9f062c9020561605b6efeca60186396f Mon Sep 17 00:00:00 2001 From: Quantum Date: Wed, 9 Sep 2020 13:13:30 -0400 Subject: [PATCH] Fix non-power-of-two random number generation --- src/generator.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/generator.js b/src/generator.js index 267adf4..d683026 100644 --- a/src/generator.js +++ b/src/generator.js @@ -10,6 +10,7 @@ function getWordList (name) { throw new Error(`Invalid word list: ${name}`) } +// Only works when the maximum possible value in indices is divisible by list.length. function getWords (list, indices) { return Array.from(indices).map(index => list[index % list.length]) } @@ -18,21 +19,25 @@ function capitalize (string) { return string[0].toUpperCase() + string.slice(1) } +// Only works on power-of-two sized lists. function pickWords (list, number) { const array = new Uint16Array(number) window.crypto.getRandomValues(array) return getWords(list, array) } +// Only works when the maximum possible value of index is divisible by choices.length. function getChar (choices, index) { return choices[index % choices.length] } function pickChar (choices) { const array = new Uint32Array(1) - window.crypto.getRandomValues(array) - const index = array[0] - return getChar(choices, index) + const maxValid = Math.floor(4294967296 / choices.length) * choices.length; + do { + window.crypto.getRandomValues(array) + } while (array[0] >= maxValid) + return getChar(choices, array[0]) } function generate (options) {