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

@diplomatiq/crypto-random

v3.0.0

Published

Generate cryptographically strong, uniformly distributed random integers from custom intervals, strings from custom character sets, and boolean values.

Downloads

987

Readme

TypeScript library for generating cryptographically strong, uniformly distributed random integers from custom intervals, strings from custom character sets, and boolean values.


Installation

Being an npm package, you can install crypto-random with the following command:

npm install -P @diplomatiq/crypto-random

Testing

Run tests with the following:

npm test

Besides basic input-output and format tests, the core generation logic is also tested if it correctly produces its output following a uniform distribution. These tests can fail with a minimal probability, and that's fine. The underlying default PRNGs are always considered to be cryptographically secure, so the actual randomness of the output is not tested.

Usage

Note: This package is built as an ES6 package. You will not be able to use require().

After installation, import the RandomGenerator class into your project, and use its async API after instantiation:

import { RandomGenerator } from '@diplomatiq/crypto-random';

// …

async function main() {
    const randomGenerator = new RandomGenerator();
    const randomString = await randomGenerator.alphanumeric(32);
    // randomString will contain a 32-character-long alphanumeric string
}

From version 2.0, only browser environments are supported out of the box (the default entropy source being window.crypto.getRandomValues). But with minimal additional work, you can inject any other entropy source (e.g. for using crypto-random in a Node.js environment). For more information, see the Using other entropy sources section below.

API

All the API methods return Promises.

The below referenced MAX_ALPHABET_LEN value determines the maximum number of elements of an alphabet used for generating random values: MAX_ALPHABET_LEN = 4294967296.

bytes(byteCount: number): Promise<Uint8Array>;

/**
 * Returns an array of @param byteCount length filled with cryptographically strong random bytes.
 */
bytes(byteCount: number): Promise<Uint8Array>;

integer(min: number, max: number, howMany = 1, unique = false): Promise<number[]>;

/**
 * Returns a cryptographically strong randomly generated positive integer between @param min and @param max,
 * inclusive.
 * The lowest possible value of @param min is 0.
 * The highest possible value of @param max is @var Number.MAX_SAFE_INTEGER.
 * The @param max - @param min + 1 <= @member MAX_ALPHABET_LEN inequality must be kept true.
 *
 * If needing more than one integer at once from a given interval, use @param howMany. This will reduce the number
 * of times calling the crypto API, making the execution faster.
 *
 * If generating more than one integers with @param unique = true,
 * the generated integers will be unique in the returned set.
 */
integer(min: number, max: number, howMany = 1, unique = false): Promise<number[]>;

string(alphabet: string, desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated string value with a @param desiredLength length
 * from a given @param alphabet.
 *
 * If generating with @param unique = true, the characters in the string will be unique.
 */
string(alphabet: string, desiredLength: number, unique = false): Promise<string>;

lowercase(desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated string with lowercase letters only.
 */
lowercase(desiredLength: number, unique = false): Promise<string>;

uppercase(desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated string with uppercase letters only.
 */
uppercase(desiredLength: number, unique = false): Promise<string>;

numeric(desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated string with numeric characters only.
 */
numeric(desiredLength: number, unique = false): Promise<string>;

alphabetic(desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated string with lower- and uppercase letters only.
 */
alphabetic(desiredLength: number, unique = false): Promise<string>;

alphanumeric(desiredLength: number, unique = false): Promise<string>;

/**
 * Returns a cryptographically strong randomly generated alphanumeric string.
 */
alphanumeric(desiredLength: number, unique = false): Promise<string>;

boolean(): Promise<boolean>;

/**
 * Returns a cryptographically strong randomly generated boolean value.
 */
boolean(): Promise<boolean>;

Entropy sources

Default entropy source

Providing no arguments in the constructor, the RandomGenerator is instantiated using the default BrowserEntropyProvider as its entropy source. This will look for window.crypto.getRandomValues.

type UnsignedTypedArray = Uint8Array | Uint16Array | Uint32Array;
interface EntropyProvider {
    getRandomValues<T extends UnsignedTypedArray>(array: T): T | Promise<T>;
}
class RandomGenerator {
    /**
     * Provides entropy in the form of random-filled typed arrays.
     */
    private readonly entropyProvider: EntropyProvider;

    constructor(entropyProvider: EntropyProvider = new BrowserEntropyProvider()) {
        this.entropyProvider = entropyProvider;
    }

    // …
}

Using other entropy sources

You can inject any entropy source into the RandomGenerator as long as it implements the required EntropyProvider interface specified above.

E.g. in your Node.js application, you can create nodeJsEntropyProvider.ts:

import { EntropyProvider, UnsignedTypedArray } from '@diplomatiq/crypto-random';
import { randomFill } from 'crypto';

export class NodeJsEntropyProvider implements EntropyProvider {
    public async getRandomValues<T extends UnsignedTypedArray>(array: T): Promise<T> {
        return new Promise<T>((resolve, reject): void => {
            randomFill(array, (error: Error | null, array: T): void => {
                if (error !== null) {
                    reject(error);
                    return;
                }
                resolve(array);
            });
        });
    }
}

And then (still in your Node.js application) use RandomGenerator as follows:

import { RandomGenerator } from '@diplomatiq/crypto-random';
import { NodeJsEntropyProvider } from './nodeJsEntropyProvider';

// …

async function main() {
    const entropyProvider = new NodeJsEntropyProvider();
    const randomGenerator = new RandomGenerator(entropyProvider);
    const randomString = await randomGenerator.alphanumeric(32);
    // randomString will contain a 32-character-long alphanumeric string
}

Using a custom entropy source

WARNING! Unless you are a seasoned cryptography expert possessing comprehensive knowledge about random/pseudo-random value generation, DO NOT use any custom entropy source implementation other than the default, or found in well-tested, popular cryptographic libraries survived many years under public scrutiny. Cryptography — and mostly random generation — can be messed up very easily. If you use anything else than a CSPRNG/TRNG for gathering entropy, the values you generate using that entropy source will not be random in the cryptographic meaning, and thus will NOT be suitable for being used as passwords/keys/nonces/etc.

Discrete uniform distribution

In this library's context, discrete uniform distribution means that any character from a given alphabet will be chosen with equal probability into the generated random value. At generating any kind of cryptographic keys (passwords, authentication tokens, nonces), uniform distribution is crucial: in every other case the size of the key space decreases in some degree (thus finding the key is easier).

This library generates its random values following a discrete uniform distribution.

Development

See CONTRIBUTING.md for details.


Copyright (c) 2018 Diplomatiq