logo

Programming Languages - Random Number Generation

Random number generation in programming is divided into two fundamentally different categories:

  1. Pseudo-Random Number Generators (PRNGs): Fast, deterministic algorithms (like Mersenne Twister or PCG). Given the same initial seed, they produce the exact same sequence of numbers. Designed for simulations, games, and statistical sampling.
  2. Cryptographically Secure PRNGs (CSPRNGs): Backed by operating system entropy pools (such as /dev/urandom, getrandom(), or Windows CryptoAPI). Unpredictable and non-reproducible. Required for session tokens, passwords, cryptography, and UUID generation.

Security Rule: Never use general PRNGs (Math.random(), random.random(), rand()) for security-sensitive tasks, passwords, or authentication tokens. Attackers can reconstruct the internal PRNG state from a few generated outputs and predict all future tokens.

JavaScript & Node.js

PRNG (Fast, Non-Cryptographic)

// Floating point number in [0, 1)
const floatVal = Math.random();

// Integer within range [min, max]
function getRandomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

CSPRNG (Cryptographically Secure)

// Modern Web API (Browsers & Node.js 19+)
const randomBytes = new Uint8Array(16);
crypto.getRandomValues(randomBytes);

// Node.js 'crypto' module
import crypto from 'node:crypto';
const token = crypto.randomBytes(32).toString('hex');
const secureInt = crypto.randomInt(1, 100); // Thread-safe, unbiased random integer

Python

PRNG (random module)

Uses the Mersenne Twister algorithm (MT19937). Period of 219937−12^{19937} - 1.

import random

val = random.random()               # Float in [0.0, 1.0)
int_val = random.randint(1, 10)     # Integer in [1, 10] (inclusive)
choice = random.choice(['a', 'b', 'c'])
random.shuffle(my_list)             # In-place shuffle

CSPRNG (secrets module)

Introduced in Python 3.6 to prevent accidental misuse of random for security:

import secrets

token_hex = secrets.token_hex(16)         # 32-character hex token
token_url = secrets.token_urlsafe(32)     # Base64 URL-safe token
secure_int = secrets.randbelow(100)       # Secure int in [0, 99]

Go

PRNG (math/rand/v2 - Go 1.22+)

Go 1.22 introduced math/rand/v2, which automatically seeds per-thread generators and uses the fast PCG / ChaCha8 algorithms:

package main

import (
    "fmt"
    "math/rand/v2"
)

func main() {
    val := rand.Float64()       // Float in [0.0, 1.0)
    intVal := rand.IntN(100)    // Int in [0, 99]
    fmt.Println(val, intVal)
}

CSPRNG (crypto/rand)

Reads directly from kernel entropy:

package main

import (
    "crypto/rand"
    "encoding/hex"
    "fmt"
)

func generateToken(n int) (string, error) {
    b := make([]byte, n)
    if _, err := rand.Read(b); err != nil {
        return "", err
    }
    return hex.EncodeToString(b), nil
}

Rust

Rust does not include random number generation in the standard library (std), relying on the standard rand crate:

[dependencies]
rand = "0.8"
use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();

    // Random float & range
    let n: f64 = rng.gen();
    let dice: u32 = rng.gen_range(1..=6);

    // Cryptographically secure generation (via OS RNG)
    let secure_bytes: [u8; 32] = rand::random();
}

C++ (<random>)

Modern C++11 discarded legacy C rand() (which had poor distribution and tiny ranges) in favor of decoupled engines and distributions:

#include <iostream>
#include <random>

int main() {
    // 1. Hardware entropy source for seeding
    std::random_device rd;

    // 2. Mersenne Twister engine
    std::mt19937 gen(rd());

    // 3. Uniform integer distribution [1, 100]
    std::uniform_int_distribution<int> distrib(1, 100);

    for (int i = 0; i < 5; ++i) {
        std::cout << distrib(gen) << " ";
    }
}

Summary & Security Matrix

Language Default PRNG CSPRNG Module Underlying Kernel Source
JavaScript Math.random() (Xoroshiro128+) crypto.getRandomValues() /dev/urandom / Windows BCrypt
Python random (Mersenne Twister) secrets / os.urandom() getrandom(2) / /dev/urandom
Go math/rand/v2 (PCG / ChaCha8) crypto/rand getrandom(2) / /dev/urandom
Rust rand::thread_rng() rand::rngs::OsRng getrandom syscall
C++ <random> (std::mt19937) OS APIs or std::random_device Platform-dependent