php-random-int

An unbiased CSPRNG inspired by PHP's random_int.

Usage no npm install needed!

<script type="module">
  import phpRandomInt from 'https://cdn.skypack.dev/php-random-int';
</script>

README

php-random-int

An unbiased CSPRNG inspired by PHP 7's random_int function, adapted from PHP 5's userland implementation of the function (up to date with release version 2.0.18), utilizing Node.js's crypto.randomBytes as a secure entropy source.

Call the function with two arguments, a minimum and a maximum. The function will return an unbiased cryptographically secure pseudorandom number between the minimum and maximum, inclusive. (The minimum, the maximum, and the size of the interval between them must all be 32-bit integers.)

const randomInt = require('php-random-int');

// Simulates rolling a fair 20-sided die.
console.log(randomInt(1, 20));

My goal is to adapt PHP 7's random_int function as closely as possible so that developers migrating applications from PHP to Node.js have a convenient alternative that behaves in a consistent fashion with the CSPRNG they are familiar with. Moreover, many alternatives had dubious documentation or dependencies. I wanted an implementation that is easy to verify and uses only built-in modules.

This algorithm avoids bias by generating up to 128 random integers with the right number of bits until it finds one that fits the given interval, rather than generating a single random integer and using modulus division to force it into the interval, which would skew the distribution. If the entropy source (crypto.randomBytes) is uniform, it's astronomically improbable for the algorithm to try more than the allotted 128 (2^7) integers. It tries exactly 1 integer when the interval size is a power of 2, usually less than 8 (2^3) integers for most practical interval sizes, and usually less than 32 (2^5) integers for degenerate interval sizes in my testing.

Please let me know if you discover any bias or cryptographically insecure properties in this implementation of the algorithm.