Skip to content

Commit

Permalink
crypto: fix randomInt bias
Browse files Browse the repository at this point in the history
Co-authored-by: Andrey Pechkurov <apechkurov@gmail.com>

PR-URL: #36894
Refs: #34600
Reviewed-By: Andrey Pechkurov <apechkurov@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
tniessen authored and targos committed May 1, 2021
1 parent fa82cbc commit 00659a9
Showing 1 changed file with 9 additions and 10 deletions.
19 changes: 9 additions & 10 deletions lib/internal/crypto/random.js
Expand Up @@ -176,30 +176,29 @@ function randomInt(min, max, callback) {
`<= ${RAND_MAX}`, range);
}

const excess = RAND_MAX % range;
const randLimit = RAND_MAX - excess;
// For (x % range) to produce an unbiased value greater than or equal to 0 and
// less than range, x must be drawn randomly from the set of integers greater
// than or equal to 0 and less than randLimit.
const randLimit = RAND_MAX - (RAND_MAX % range);

if (isSync) {
// Sync API
while (true) {
const x = randomBytes(6).readUIntBE(0, 6);
// If x > (maxVal - (maxVal % range)), we will get "modulo bias"
if (x > randLimit) {
// Try again
if (x >= randLimit) {
// Try again.
continue;
}
const n = (x % range) + min;
return n;
return (x % range) + min;
}
} else {
// Async API
const pickAttempt = () => {
randomBytes(6, (err, bytes) => {
if (err) return callback(err);
const x = bytes.readUIntBE(0, 6);
// If x > (maxVal - (maxVal % range)), we will get "modulo bias"
if (x > randLimit) {
// Try again
if (x >= randLimit) {
// Try again.
return pickAttempt();
}
const n = (x % range) + min;
Expand Down

0 comments on commit 00659a9

Please sign in to comment.