npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

secure-random-uniform

v4.0.0

Published

Generate secure, random, uniform integers, compensating for modulo bias

Downloads

438

Readme

secure-random-uniform

Generate secure, random, uniform integers, compensating for modulo bias

Usage

var secureRandom = require('secure-random-uniform')

// Numbers from [0, 2000)
secureRandom(2000)

// Numbers from [100, 110)
secureRandom(10) + 100

// Numbers from [-10, 10]
secureRandom(21) - 10

BigInt support (Experimental!)

var secureRandom = require('secure-random-uniform/bigint')

// Numbers from [0, 2^64)
secureRandom(2n ** 64n)

// Numbers from [0, googol)
secureRandom(10n ** 100n)

API

var num = secureRandomUniform(limit)

Returns a number from the uniform distribution [0, limit) (limit exclusive). Note that limit must not be larger than 2^53 - 1 (Number.MAX_SAFE_INTEGER).

Background

Modulo reduction: Bytes to integers

A naive implementation might look like:

function insecureRandom (limit) {
  return secureRandomSource() % limit
}

However this will only yield a uniform distribution if limit is a divisor of whatever is the maximum value of secureRandomSource(). Consider limit = 3 and the maximum value returned by secureRandomSource() being 5. Then in the long run the frequency of numbers returned will be [0 = 2/5, 1 = 2/5, 2 = 1/5], causing the distribution to be skewed (ie. not uniform). This is called "Modulo Bias".

This module borrows from arc4random_uniform and keeps generating a new random number until it hits a range that's congruent to limit. This is not as bad as it sounds. The worst case is if limit ≈ (2^48 - 1) / 2, in which case it will have a ~ 0.5 chance of doing a redraw. The number of redraws required can be modelled by as 0.5^(redraws) which quickly converges towards zero. In practise only one draw is required on average.

See verify-modulo-reduction.js for a deterministic test of the algorithm

Random bytes to integers

The next issue is transforming random bytes into unsigned numbers. We can efficiently transform bytes into signed 32-bit integers in JS with:

(byte[3] << 24) | (byte[2] << 16) | (byte[1] << 8) | (byte[0])

To make the number unsigned we can do a zero-fill right shift, which will cause the sign bit to become 0:

((byte[3] << 24) | (byte[2] << 16) | (byte[1] << 8) | (byte[0])) >>> 0

To go beyond 32-bit integers, to the maximum of 53-bit integers representable in Javascript Numbers (IEEE 754), we can construct the remaining 21 bits and move them up using a floating point multiplication.

((((buf[6] & 0b00011111) << 16) | (buf[5] << 8) | (buf[4])) >>> 0) * 0x100000000
+ (((byte[3] << 24) | (byte[2] << 16) | (byte[1] << 8) | (byte[0])) >>> 0)

Note that the bitwise operations have been wrapped in parenthesis, otherwise the add and multiplication operation will become 32-bit operations, reducing the number modulo 2^32

See verify-readle.js for verification against a known implementation of converting bytes to unsigned integers.

License

ISC