RocketChat/Rocket.Chat

View on GitHub
packages/random/src/NodeRandomGenerator.ts

Summary

Maintainability
A
0 mins
Test Coverage
import crypto from 'crypto';

import { AleaRandomGenerator } from './AleaRandomGenerator';
import { RandomGenerator } from './RandomGenerator';
import { createAleaGeneratorWithGeneratedSeed } from './createAleaGenerator';

export class NodeRandomGenerator extends RandomGenerator {
    /**
     * @name Random.fraction
     * @summary Return a number between 0 and 1, like `Math.random`.
     * @locus Anywhere
     */
    fraction() {
        const numerator = Number.parseInt(this.hexString(8), 16);
        return numerator * 2.3283064365386963e-10; // 2^-3;
    }

    /**
     * @name Random.hexString
     * @summary Return a random string of `n` hexadecimal digits.
     * @locus Anywhere
     * @param digits Length of the string
     */
    hexString(digits: number) {
        const numBytes = Math.ceil(digits / 2);
        let bytes;
        // Try to get cryptographically strong randomness. Fall back to
        // non-cryptographically strong if not available.
        try {
            bytes = crypto.randomBytes(numBytes);
        } catch (e) {
            // XXX should re-throw any error except insufficient entropy
            bytes = crypto.pseudoRandomBytes(numBytes);
        }
        const result = bytes.toString('hex');
        // If the number of digits is odd, we'll have generated an extra 4 bits
        // of randomness, so we need to trim the last digit.
        return result.substring(0, digits);
    }

    /**
     * @name Random.between Returns a random integer between min and max, inclusive.
     * @param min Minimum value (inclusive)
     * @param max Maximum value (inclusive)
     * @returns A random integer between min and max, inclusive.
     */
    between(min: number, max: number) {
        return Math.floor(this.fraction() * (max - min + 1)) + min;
    }

    protected safelyCreateWithSeeds(...seeds: readonly unknown[]) {
        return new AleaRandomGenerator({ seeds });
    }

    insecure: RandomGenerator = createAleaGeneratorWithGeneratedSeed();
}