Complete Guide to Random Data Generation: Strings, Numbers, and JSON
Master random data generation for testing and development. Learn cryptographically secure vs pseudo-random, seeding, distribution, and practical applications in JavaScript and Python.
Introduction to Random Data Generation
Random data generation is essential for testing, development, and data analysis. Whether you're creating test databases, generating unique identifiers, or simulating user behavior, understanding random data generation techniques is crucial.
This comprehensive guide covers everything from basic random string generation to advanced techniques including cryptographically secure randomness, seeding for reproducibility, and generating complex JSON structures.
What You'll Learn
- Generating random strings with custom character sets
- Creating random numbers with specific distributions
- Building random JSON objects for API testing
- Cryptographically secure vs pseudo-random generation
- Seeding for reproducible random data
- Best practices for test data generation
Random String Generation
Random strings are used for passwords, tokens, session IDs, and test data. Different use cases require different character sets and security levels.
Basic Random String
Custom Character Sets
Cryptographically Secure Strings
Common Character Sets
- Alphanumeric: A-Z, a-z, 0-9 (62 characters)
- Hexadecimal: 0-9, a-f (16 characters)
- Base64: A-Z, a-z, 0-9, +, / (64 characters)
- URL-Safe: A-Z, a-z, 0-9, -, _ (64 characters)
- Digits Only: 0-9 (10 characters)
- Letters Only: A-Z, a-z (52 characters)
Password Generation
Random Number Generation
Random numbers are fundamental to simulations, games, sampling, and testing. Understanding distributions and ranges is key to generating useful random data.
Basic Random Numbers
Random Integers in Range
Random Floats with Precision
Cryptographically Secure Numbers
Common Distributions
- Uniform: Equal probability for all values
- Normal (Gaussian): Bell curve distribution
- Exponential: For modeling time between events
- Poisson: For counting events in fixed interval
Normal Distribution
Boost Your Development Workflow
Professional developer tools suite - Format, validate, and optimize your code in seconds
Random JSON Generation
Generate complex JSON structures for API testing, mock data, and database seeding. Random JSON is invaluable for testing edge cases and load testing.
Simple Random Objects
Complex Nested JSON
Random Arrays
Schema-Based Generation
Realistic Test Data
Cryptographically Secure vs Pseudo-Random
Understanding the difference between cryptographically secure and pseudo-random generation is crucial for security and performance.
Pseudo-Random (Math.random)
Cryptographically Secure
When to Use Each
Security Considerations
- Use Crypto for: Passwords, tokens, session IDs, security keys
- Use Pseudo for: Games, simulations, test data, UI elements
- Never use Math.random() for: Security-critical applications
- Performance: Crypto is slower but necessary for security
Seeding for Reproducible Randomness
Seeded random generation produces reproducible sequences, essential for testing, debugging, and scientific simulations.
Seeded Random Number Generator
Using Seeds for Testing
Multiple Independent Streams
Benefits of Seeding
- Reproducible test scenarios for debugging
- Consistent benchmarking across runs
- Deterministic simulations for scientific research
- Ability to recreate specific test cases
- Version control for random test data
UUIDs and GUIDs Generation
UUIDs (Universally Unique Identifiers) provide globally unique IDs for databases, distributed systems, and APIs.
UUID v4 (Random)
UUID v1 (Time-Based)
Short Unique IDs
UUID Versions
- v1: Time-based with MAC address (not recommended for privacy)
- v3: Name-based using MD5 hashing
- v4: Random (most common, cryptographically secure)
- v5: Name-based using SHA-1 hashing
Use Cases
- Database primary keys in distributed systems
- Session identifiers and tokens
- File and resource naming
- Message and transaction IDs
- API request tracking
Test Data Generation Patterns
Effective test data generation requires realistic patterns that cover edge cases while being diverse enough for comprehensive testing.
User Data Generation
Date and Time Generation
Email and Phone Generation
Address Generation
E-commerce Test Data
Random Data in Testing Frameworks
Integrate random data generation into testing frameworks for property-based testing and fuzzing.
Jest/Vitest Integration
Property-Based Testing
Fuzzing with Random Data
Snapshot Testing with Seeds
Best Practices for Random Data Generation
Follow these best practices to generate effective, secure, and useful random data:
1. Choose the Right Randomness Level
- Use crypto for security-critical applications
- Use pseudo-random for performance-critical non-security tasks
- Use seeding for reproducible tests
- Document which type you're using and why
2. Test Edge Cases
3. Validate Generated Data
4. Performance Optimization
- Cache character sets for repeated generation
- Batch generate data when possible
- Use appropriate data structures (TypedArray for numbers)
- Consider memory usage for large datasets
5. Data Diversity
- Include boundary values (min, max, zero, negative)
- Test with empty and null values
- Include special characters and Unicode
- Vary data sizes from small to large
6. Security Considerations
Conclusion
Random data generation is a powerful tool for testing, development, and simulation. By understanding the differences between pseudo-random and cryptographically secure generation, using seeding appropriately, and following best practices, you can create effective test scenarios and secure applications.
Key takeaways:
- Use cryptographically secure random for security-critical applications
- Pseudo-random is sufficient for testing and simulations
- Seeding enables reproducible random data for debugging
- UUIDs provide globally unique identifiers for distributed systems
- Generate realistic test data that covers edge cases
- Validate generated data to ensure it meets requirements
- Choose appropriate distributions for your use case
- Document your randomness approach for other developers
Try our free random data generators: Random String, Random Number, Random JSON, and UUID Generator!
// Generate random string
function randomString(length = 10) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
}
return result;
}
console.log(randomString(16));
// Example: "aB3xKp9mNq2Lv8Rt"
// Using Array methods
function randomStringAlt(length = 10) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return Array.from({ length }, () =>
chars.charAt(Math.floor(Math.random() * chars.length))
).join('');
}
// Python version
"""
import random
import string
def random_string(length=10):
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(length))
print(random_string(16))
""" // Predefined character sets
const CHARSETS = {
alphanumeric: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
lowercase: 'abcdefghijklmnopqrstuvwxyz',
digits: '0123456789',
hex: '0123456789abcdef',
base64: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
urlSafe: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_',
symbols: '!@#$%^&*()_+-=[]{}|;:,.<>?'
};
// Generate with custom charset
function randomString(length, charset = 'alphanumeric') {
const chars = typeof charset === 'string' && CHARSETS[charset]
? CHARSETS[charset]
: charset;
return Array.from({ length }, () =>
chars.charAt(Math.floor(Math.random() * chars.length))
).join('');
}
console.log(randomString(16, 'hex')); // "3a7f9e2b8c1d4f6a"
console.log(randomString(12, 'uppercase')); // "MKPQRTUVWXYZ"
console.log(randomString(8, 'digits')); // "94721856"
// Custom character set
const vowels = 'aeiou';
console.log(randomString(10, vowels)); // "aeiouiaeuo" // Cryptographically secure random string (Node.js)
const crypto = require('crypto');
function secureRandomString(length = 16) {
const bytes = crypto.randomBytes(length);
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let result = '';
for (let i = 0; i < length; i++) {
result += chars[bytes[i] % chars.length];
}
return result;
}
// Browser crypto API
function secureRandomStringBrowser(length = 16) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const array = new Uint8Array(length);
crypto.getRandomValues(array);
return Array.from(array, byte => chars[byte % chars.length]).join('');
}
// Secure hex string
function secureHex(length = 32) {
return crypto.randomBytes(length).toString('hex');
}
// Secure base64 string
function secureBase64(length = 32) {
return crypto.randomBytes(length).toString('base64');
}
console.log(secureRandomString(32));
console.log(secureHex(16));
console.log(secureBase64(24)); // Generate secure password with requirements
function generatePassword(options = {}) {
const {
length = 16,
includeUppercase = true,
includeLowercase = true,
includeDigits = true,
includeSymbols = true,
minUppercase = 1,
minLowercase = 1,
minDigits = 1,
minSymbols = 1
} = options;
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
const digits = '0123456789';
const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
let chars = '';
let password = '';
// Build character set
if (includeUppercase) chars += uppercase;
if (includeLowercase) chars += lowercase;
if (includeDigits) chars += digits;
if (includeSymbols) chars += symbols;
// Ensure minimum requirements
if (includeUppercase) {
for (let i = 0; i < minUppercase; i++) {
password += uppercase[Math.floor(Math.random() * uppercase.length)];
}
}
if (includeLowercase) {
for (let i = 0; i < minLowercase; i++) {
password += lowercase[Math.floor(Math.random() * lowercase.length)];
}
}
if (includeDigits) {
for (let i = 0; i < minDigits; i++) {
password += digits[Math.floor(Math.random() * digits.length)];
}
}
if (includeSymbols) {
for (let i = 0; i < minSymbols; i++) {
password += symbols[Math.floor(Math.random() * symbols.length)];
}
}
// Fill remaining length
while (password.length < length) {
password += chars[Math.floor(Math.random() * chars.length)];
}
// Shuffle password
return password.split('').sort(() => Math.random() - 0.5).join('');
}
console.log(generatePassword({ length: 20, includeSymbols: true })); // Random float between 0 and 1
const random = Math.random();
console.log(random); // 0.123456789
// Random float in range [min, max)
function randomFloat(min, max) {
return Math.random() * (max - min) + min;
}
console.log(randomFloat(10, 20)); // 15.7834
// Random integer in range [min, max]
function randomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(randomInt(1, 100)); // 42
// Random from array
function randomChoice(array) {
return array[Math.floor(Math.random() * array.length)];
}
console.log(randomChoice(['red', 'green', 'blue'])); // "green"
// Python version
"""
import random
# Float between 0 and 1
random.random()
# Float in range
random.uniform(10, 20)
# Integer in range
random.randint(1, 100)
# Choice from list
random.choice(['red', 'green', 'blue'])
""" // Inclusive range [min, max]
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// Exclusive range [min, max)
function randomIntExclusive(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
// Weighted random integer
function weightedRandomInt(weights) {
const total = weights.reduce((sum, w) => sum + w, 0);
let random = Math.random() * total;
for (let i = 0; i < weights.length; i++) {
random -= weights[i];
if (random <= 0) return i;
}
return weights.length - 1;
}
// Example: 50% chance of 0, 30% of 1, 20% of 2
const result = weightedRandomInt([50, 30, 20]);
// Random multiple unique integers
function randomUniqueInts(count, min, max) {
const range = max - min + 1;
if (count > range) {
throw new Error('Count exceeds available range');
}
const numbers = new Set();
while (numbers.size < count) {
numbers.add(randomInt(min, max));
}
return Array.from(numbers);
}
console.log(randomUniqueInts(5, 1, 10)); // [3, 7, 2, 9, 5] // Random float with specific decimal places
function randomFloatPrecision(min, max, decimals = 2) {
const value = Math.random() * (max - min) + min;
return parseFloat(value.toFixed(decimals));
}
console.log(randomFloatPrecision(0, 100, 2)); // 45.67
// Random percentage
function randomPercentage(decimals = 2) {
return randomFloatPrecision(0, 100, decimals);
}
console.log(randomPercentage(1)); // 73.4
// Random price
function randomPrice(min = 0.01, max = 999.99) {
return randomFloatPrecision(min, max, 2);
}
console.log('$' + randomPrice(10, 100)); // $45.89
// Random coordinate
function randomCoordinate() {
return {
lat: randomFloatPrecision(-90, 90, 6),
lng: randomFloatPrecision(-180, 180, 6)
};
}
console.log(randomCoordinate());
// { lat: 34.052235, lng: -118.243683 } // Cryptographically secure random integer (Node.js)
const crypto = require('crypto');
function secureRandomInt(min, max) {
const range = max - min + 1;
const bytesNeeded = Math.ceil(Math.log2(range) / 8);
const maxValue = Math.pow(256, bytesNeeded);
const randomBytes = crypto.randomBytes(bytesNeeded);
const randomValue = randomBytes.readUIntBE(0, bytesNeeded);
// Avoid modulo bias
if (randomValue >= maxValue - (maxValue % range)) {
return secureRandomInt(min, max);
}
return min + (randomValue % range);
}
// Browser crypto API
function secureRandomIntBrowser(min, max) {
const range = max - min + 1;
const array = new Uint32Array(1);
crypto.getRandomValues(array);
const randomValue = array[0];
return min + (randomValue % range);
}
// Secure random float
function secureRandomFloat() {
const bytes = crypto.randomBytes(4);
const value = bytes.readUInt32BE(0);
return value / 0xFFFFFFFF;
}
console.log(secureRandomInt(1, 100));
console.log(secureRandomFloat()); // Box-Muller transform for normal distribution
function randomNormal(mean = 0, stdDev = 1) {
const u1 = Math.random();
const u2 = Math.random();
const z0 = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2);
return z0 * stdDev + mean;
}
// Generate normal distribution sample
const samples = Array.from({ length: 1000 }, () =>
randomNormal(100, 15) // Mean=100, StdDev=15
);
// Calculate statistics
const avg = samples.reduce((a, b) => a + b) / samples.length;
console.log('Average:', avg.toFixed(2)); // ~100
// Exponential distribution
function randomExponential(lambda = 1) {
return -Math.log(1 - Math.random()) / lambda;
}
// Poisson distribution (approximation)
function randomPoisson(lambda) {
const L = Math.exp(-lambda);
let k = 0;
let p = 1;
do {
k++;
p *= Math.random();
} while (p > L);
return k - 1;
}
console.log(randomPoisson(5)); // Events with average rate 5 // Generate simple random JSON object
function randomObject() {
return {
id: Math.floor(Math.random() * 1000000),
name: randomString(10),
value: Math.random() * 100,
active: Math.random() > 0.5,
timestamp: new Date().toISOString()
};
}
console.log(randomObject());
// {
// id: 482756,
// name: "xKp9mNq2Lv",
// value: 73.45,
// active: true,
// timestamp: "2025-01-02T10:30:00.000Z"
// }
// Random JSON with specific types
function randomJSON(types = {}) {
const result = {};
for (const [key, type] of Object.entries(types)) {
switch (type) {
case 'string':
result[key] = randomString(10);
break;
case 'number':
result[key] = Math.random() * 100;
break;
case 'boolean':
result[key] = Math.random() > 0.5;
break;
case 'null':
result[key] = null;
break;
case 'array':
result[key] = Array.from({ length: 5 }, () => Math.random());
break;
}
}
return result;
}
const schema = { name: 'string', age: 'number', active: 'boolean' };
console.log(randomJSON(schema)); // Generate complex nested JSON
function randomNestedJSON(depth = 3, maxChildren = 5) {
if (depth === 0) {
return randomPrimitive();
}
const type = Math.random();
if (type < 0.3) {
// Object
const obj = {};
const numProps = Math.floor(Math.random() * maxChildren) + 1;
for (let i = 0; i < numProps; i++) {
const key = randomString(8);
obj[key] = randomNestedJSON(depth - 1, maxChildren);
}
return obj;
} else if (type < 0.6) {
// Array
const length = Math.floor(Math.random() * maxChildren) + 1;
return Array.from({ length }, () =>
randomNestedJSON(depth - 1, maxChildren)
);
} else {
// Primitive
return randomPrimitive();
}
}
function randomPrimitive() {
const types = ['string', 'number', 'boolean', 'null'];
const type = types[Math.floor(Math.random() * types.length)];
switch (type) {
case 'string': return randomString(10);
case 'number': return Math.random() * 100;
case 'boolean': return Math.random() > 0.5;
case 'null': return null;
}
}
console.log(JSON.stringify(randomNestedJSON(3), null, 2)); // Generate random arrays
function randomArray(length, generator) {
return Array.from({ length }, generator);
}
// Random number array
const numbers = randomArray(10, () => Math.random() * 100);
// Random string array
const strings = randomArray(5, () => randomString(8));
// Random object array
const objects = randomArray(3, () => ({
id: Math.floor(Math.random() * 1000),
name: randomString(10)
}));
// Random mixed array
function randomMixedArray(length) {
const generators = [
() => randomString(8),
() => Math.random() * 100,
() => Math.random() > 0.5,
() => null,
() => ({ nested: randomString(5) })
];
return Array.from({ length }, () => {
const gen = generators[Math.floor(Math.random() * generators.length)];
return gen();
});
}
console.log(randomMixedArray(10));
// Random matrix
function randomMatrix(rows, cols) {
return Array.from({ length: rows }, () =>
Array.from({ length: cols }, () => Math.random())
);
}
console.log(randomMatrix(3, 3)); // Schema-based JSON generation
function generateFromSchema(schema) {
const result = {};
for (const [key, config] of Object.entries(schema)) {
result[key] = generateValue(config);
}
return result;
}
function generateValue(config) {
const { type, min, max, length, items, properties } = config;
switch (type) {
case 'string':
return randomString(length || 10);
case 'number':
return randomInt(min || 0, max || 100);
case 'boolean':
return Math.random() > 0.5;
case 'array':
const arrayLength = length || 5;
return Array.from({ length: arrayLength }, () =>
generateValue(items)
);
case 'object':
return generateFromSchema(properties);
case 'enum':
return config.values[Math.floor(Math.random() * config.values.length)];
default:
return null;
}
}
// Example schema
const userSchema = {
id: { type: 'number', min: 1, max: 1000000 },
username: { type: 'string', length: 12 },
email: { type: 'string', length: 20 },
age: { type: 'number', min: 18, max: 100 },
active: { type: 'boolean' },
role: { type: 'enum', values: ['admin', 'user', 'guest'] },
tags: {
type: 'array',
length: 3,
items: { type: 'string', length: 8 }
},
settings: {
type: 'object',
properties: {
theme: { type: 'enum', values: ['light', 'dark'] },
notifications: { type: 'boolean' }
}
}
};
console.log(JSON.stringify(generateFromSchema(userSchema), null, 2)); // Generate realistic test data
const FIRST_NAMES = ['John', 'Jane', 'Bob', 'Alice', 'Charlie', 'Diana'];
const LAST_NAMES = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones'];
const DOMAINS = ['gmail.com', 'yahoo.com', 'outlook.com', 'example.com'];
function randomUser() {
const firstName = randomChoice(FIRST_NAMES);
const lastName = randomChoice(LAST_NAMES);
const username = (firstName + lastName).toLowerCase() + randomInt(100, 999);
return {
id: crypto.randomUUID(),
firstName,
lastName,
username,
email: `${username}@${randomChoice(DOMAINS)}`,
age: randomInt(18, 80),
phone: `+1-${randomInt(200, 999)}-${randomInt(200, 999)}-${randomInt(1000, 9999)}`,
address: {
street: `${randomInt(1, 9999)} ${randomChoice(['Main', 'Oak', 'Pine'])} St`,
city: randomChoice(['New York', 'Los Angeles', 'Chicago']),
state: randomChoice(['NY', 'CA', 'IL']),
zip: String(randomInt(10000, 99999))
},
createdAt: new Date(Date.now() - randomInt(0, 365 * 24 * 60 * 60 * 1000)),
lastLogin: new Date(Date.now() - randomInt(0, 30 * 24 * 60 * 60 * 1000))
};
}
function randomChoice(array) {
return array[Math.floor(Math.random() * array.length)];
}
console.log(JSON.stringify(randomUser(), null, 2));
// Generate multiple users
const users = Array.from({ length: 10 }, randomUser); // Pseudo-random with Math.random()
console.log(Math.random()); // 0.123456789
console.log(Math.random()); // 0.987654321 (unpredictable)
// Characteristics:
// - Fast performance
// - NOT cryptographically secure
// - Cannot be seeded in browsers (Node.js has seedrandom)
// - Deterministic algorithm (but seed is hidden)
// - Sufficient for games, simulations, UI
// Example: Shuffle array (Fisher-Yates)
function shuffle(array) {
const result = [...array];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
}
const cards = ['A', '2', '3', '4', '5'];
console.log(shuffle(cards));
// Good for:
// - Games and animations
// - Simulations and modeling
// - Test data generation
// - UI randomization
// - Sampling and statistics // Cryptographically secure random (Node.js)
const crypto = require('crypto');
// Random bytes
const bytes = crypto.randomBytes(16);
console.log(bytes.toString('hex'));
// Random UUID
const uuid = crypto.randomUUID();
console.log(uuid); // "550e8400-e29b-41d4-a716-446655440000"
// Browser crypto API
const array = new Uint8Array(16);
crypto.getRandomValues(array);
console.log(Array.from(array));
// Characteristics:
// - Cryptographically secure
// - Unpredictable
// - Slower than Math.random()
// - Uses OS entropy sources
// - Suitable for security applications
// Security token generation
function generateToken(bytes = 32) {
return crypto.randomBytes(bytes).toString('base64url');
}
console.log(generateToken());
// Session ID
function generateSessionId() {
return crypto.randomBytes(16).toString('hex');
}
// API key
function generateApiKey() {
return crypto.randomBytes(32).toString('base64');
}
// Use for:
// - Passwords and tokens
// - Session IDs
// - API keys
// - Encryption keys
// - Security challenges // When to use each type of randomness
// ✅ Use Math.random() for:
const gameScenarios = {
// Game mechanics
diceRoll: () => Math.floor(Math.random() * 6) + 1,
// UI animations
randomDelay: () => Math.random() * 1000,
// Test data
mockUser: () => ({
name: `User${Math.floor(Math.random() * 1000)}`,
score: Math.floor(Math.random() * 100)
}),
// Sampling
sampleArray: (arr) => arr[Math.floor(Math.random() * arr.length)]
};
// ✅ Use crypto for:
const securityScenarios = {
// Password reset tokens
resetToken: () => crypto.randomBytes(32).toString('hex'),
// Session IDs
sessionId: () => crypto.randomBytes(16).toString('base64'),
// API keys
apiKey: () => `sk_${crypto.randomBytes(24).toString('base64url')}`,
// CSRF tokens
csrfToken: () => crypto.randomBytes(32).toString('base64url'),
// Encryption keys
encryptionKey: () => crypto.randomBytes(32)
};
// ❌ NEVER use Math.random() for:
// - Passwords
// - Authentication tokens
// - Encryption keys
// - Security challenges
// - Payment verification codes // Simple seeded RNG (Linear Congruential Generator)
class SeededRandom {
constructor(seed = Date.now()) {
this.seed = seed;
}
next() {
// LCG parameters (from Numerical Recipes)
this.seed = (this.seed * 1664525 + 1013904223) % 4294967296;
return this.seed / 4294967296;
}
int(min, max) {
return Math.floor(this.next() * (max - min + 1)) + min;
}
float(min = 0, max = 1) {
return this.next() * (max - min) + min;
}
choice(array) {
return array[Math.floor(this.next() * array.length)];
}
shuffle(array) {
const result = [...array];
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(this.next() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result;
}
}
// Usage
const rng = new SeededRandom(12345);
console.log(rng.next()); // Always 0.4224... for seed 12345
console.log(rng.int(1, 100)); // Always same sequence
// Create multiple generators with same seed
const rng1 = new SeededRandom(42);
const rng2 = new SeededRandom(42);
console.log(rng1.next() === rng2.next()); // true // Use seeding for reproducible tests
describe('User generation', () => {
it('generates consistent users with same seed', () => {
const rng1 = new SeededRandom(12345);
const user1 = generateUser(rng1);
const rng2 = new SeededRandom(12345);
const user2 = generateUser(rng2);
expect(user1).toEqual(user2);
});
it('generates different users with different seeds', () => {
const user1 = generateUser(new SeededRandom(1));
const user2 = generateUser(new SeededRandom(2));
expect(user1).not.toEqual(user2);
});
});
function generateUser(rng) {
return {
id: rng.int(1, 1000000),
name: randomString(10, rng),
age: rng.int(18, 80),
score: rng.float(0, 100)
};
}
// Debugging with seeds
function debugWithSeed() {
// When bug occurs, log the seed
const seed = Date.now();
console.log('Seed:', seed);
const rng = new SeededRandom(seed);
// Now you can reproduce exact same scenario
runSimulation(rng);
}
// Version control friendly tests
// Commit the seed value to ensure same results across machines
const FIXED_SEED = 42;
const testRng = new SeededRandom(FIXED_SEED); // Multiple independent random streams
class RandomStream {
constructor(seed, streamId = 0) {
this.rng = new SeededRandom(seed + streamId);
this.streamId = streamId;
}
next() {
return this.rng.next();
}
}
// Create independent streams from same base seed
const baseSeed = 12345;
const userStream = new RandomStream(baseSeed, 0);
const itemStream = new RandomStream(baseSeed, 1);
const eventStream = new RandomStream(baseSeed, 2);
// Each stream produces different but reproducible sequences
function generateWorld(seed) {
const users = new RandomStream(seed, 0);
const terrain = new RandomStream(seed, 1);
const npcs = new RandomStream(seed, 2);
return {
users: Array.from({ length: 10 }, () => generateUser(users)),
terrain: Array.from({ length: 100 }, () => generateTerrain(terrain)),
npcs: Array.from({ length: 50 }, () => generateNPC(npcs))
};
}
// Same seed = same world, but independent randomness for each component
const world1 = generateWorld(42);
const world2 = generateWorld(42);
console.log(world1 === world2); // Deep equal // UUID v4 (Random) - Node.js built-in
const crypto = require('crypto');
const uuid = crypto.randomUUID();
console.log(uuid);
// "550e8400-e29b-41d4-a716-446655440000"
// Manual UUID v4 generation
function generateUUIDv4() {
const bytes = crypto.randomBytes(16);
// Set version (4) and variant bits
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = bytes.toString('hex');
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}
// Browser implementation
function uuidv4Browser() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
// Cryptographically secure browser version
function secureUUIDv4() {
const array = new Uint8Array(16);
crypto.getRandomValues(array);
array[6] = (array[6] & 0x0f) | 0x40;
array[8] = (array[8] & 0x3f) | 0x80;
const hex = Array.from(array, b => b.toString(16).padStart(2, '0')).join('');
return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
}
console.log(generateUUIDv4()); // UUID v1 (Time-based) - requires uuid library
// npm install uuid
import { v1 as uuidv1 } from 'uuid';
const uuid = uuidv1();
console.log(uuid);
// "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
// Manual UUID v1 (simplified)
function generateUUIDv1() {
const timestamp = Date.now();
const clockSeq = Math.floor(Math.random() * 0x4000);
// This is simplified - real v1 uses MAC address
const node = crypto.randomBytes(6);
node[0] |= 0x01; // Set multicast bit
// Convert timestamp to UUID time (100-nanosecond intervals since 1582)
const uuidTime = (timestamp + 12219292800000) * 10000;
const timeLow = (uuidTime & 0xFFFFFFFF).toString(16).padStart(8, '0');
const timeMid = ((uuidTime >> 32) & 0xFFFF).toString(16).padStart(4, '0');
const timeHi = (((uuidTime >> 48) & 0x0FFF) | 0x1000).toString(16).padStart(4, '0');
const clockSeqHi = ((clockSeq >> 8) | 0x80).toString(16).padStart(2, '0');
const clockSeqLow = (clockSeq & 0xFF).toString(16).padStart(2, '0');
const nodeHex = node.toString('hex');
return `${timeLow}-${timeMid}-${timeHi}-${clockSeqHi}${clockSeqLow}-${nodeHex}`;
}
// Note: UUID v1 includes timestamp and MAC address
// Not recommended due to privacy concerns
// Use v4 for most applications // Generate short unique IDs (not UUIDs)
function shortId(length = 8) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const bytes = crypto.randomBytes(length);
return Array.from(bytes, byte => chars[byte % chars.length]).join('');
}
console.log(shortId()); // "aB3xKp9m"
// Nano ID style (base62)
function nanoId(size = 21) {
const alphabet = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const bytes = crypto.randomBytes(size);
let id = '';
while (size--) {
id += alphabet[bytes[size] & 61]; // 61 = 0b00111101
}
return id;
}
console.log(nanoId()); // "V1StGXR8_Z5jdHi6B-myT"
// URL-safe short ID
function urlSafeId(length = 12) {
return crypto.randomBytes(length)
.toString('base64url')
.slice(0, length);
}
console.log(urlSafeId()); // "aB3xKp9mNq2L"
// Timestamp-based short ID (sortable)
function sortableId() {
const timestamp = Date.now().toString(36);
const random = crypto.randomBytes(6).toString('base64url').slice(0, 8);
return `${timestamp}-${random}`;
}
console.log(sortableId()); // "l5xr3w-aB3xKp9m" // Comprehensive user data generator
const FIRST_NAMES = ['Emma', 'Liam', 'Olivia', 'Noah', 'Ava', 'Ethan'];
const LAST_NAMES = ['Smith', 'Johnson', 'Williams', 'Brown', 'Jones'];
const CITIES = ['New York', 'Los Angeles', 'Chicago', 'Houston'];
const COMPANIES = ['Acme Corp', 'Global Tech', 'MegaSystems'];
function generateUser(rng = Math) {
const firstName = randomChoice(FIRST_NAMES, rng);
const lastName = randomChoice(LAST_NAMES, rng);
const birthYear = randomInt(1950, 2005, rng);
return {
id: crypto.randomUUID(),
username: generateUsername(firstName, lastName, rng),
email: generateEmail(firstName, lastName, rng),
firstName,
lastName,
dateOfBirth: generateDate(birthYear, rng),
age: new Date().getFullYear() - birthYear,
gender: randomChoice(['male', 'female', 'other'], rng),
phone: generatePhone(rng),
address: generateAddress(rng),
company: randomChoice(COMPANIES, rng),
jobTitle: randomChoice(['Developer', 'Manager', 'Designer'], rng),
salary: randomInt(30000, 150000, rng),
isActive: Math.random() > 0.2,
registeredAt: generatePastDate(365, rng),
lastLoginAt: generatePastDate(30, rng)
};
}
function generateUsername(first, last, rng) {
return (first + last).toLowerCase() + randomInt(100, 999, rng);
}
function generateEmail(first, last, rng) {
const domains = ['gmail.com', 'yahoo.com', 'outlook.com'];
return `${first.toLowerCase()}.${last.toLowerCase()}${randomInt(1, 99, rng)}@${randomChoice(domains, rng)}`;
}
function randomChoice(arr, rng = Math) {
return arr[Math.floor(rng.random() * arr.length)];
}
function randomInt(min, max, rng = Math) {
return Math.floor(rng.random() * (max - min + 1)) + min;
} // Random date generation
function randomDate(start, end) {
return new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
}
const pastYear = new Date(Date.now() - 365 * 24 * 60 * 60 * 1000);
const now = new Date();
console.log(randomDate(pastYear, now));
// Random past date (days ago)
function randomPastDate(maxDaysAgo = 365) {
const ms = Math.random() * maxDaysAgo * 24 * 60 * 60 * 1000;
return new Date(Date.now() - ms);
}
// Random future date
function randomFutureDate(maxDaysAhead = 365) {
const ms = Math.random() * maxDaysAhead * 24 * 60 * 60 * 1000;
return new Date(Date.now() + ms);
}
// Random timestamp in range
function randomTimestamp(startYear, endYear) {
const start = new Date(startYear, 0, 1).getTime();
const end = new Date(endYear, 11, 31).getTime();
return new Date(start + Math.random() * (end - start));
}
console.log(randomTimestamp(2020, 2025));
// Random time of day
function randomTime() {
const hours = randomInt(0, 23);
const minutes = randomInt(0, 59);
const seconds = randomInt(0, 59);
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}
// Business hours random time
function randomBusinessTime() {
const hours = randomInt(9, 17);
const minutes = randomInt(0, 59);
return `${String(hours).padStart(2, '0')}:${String(minutes).padStart(2, '0')}`;
} // Generate email addresses
function generateEmail(name, domain = null) {
const domains = domain ? [domain] : ['gmail.com', 'yahoo.com', 'outlook.com', 'example.com'];
const selectedDomain = randomChoice(domains);
const styles = [
`${name}@${selectedDomain}`,
`${name}${randomInt(1, 999)}@${selectedDomain}`,
`${name}.${randomInt(1980, 2005)}@${selectedDomain}`
];
return randomChoice(styles).toLowerCase();
}
// Generate phone numbers
function generatePhone(countryCode = '+1') {
const areaCode = randomInt(200, 999);
const exchange = randomInt(200, 999);
const subscriber = randomInt(1000, 9999);
const formats = [
`${countryCode}-${areaCode}-${exchange}-${subscriber}`,
`${countryCode} (${areaCode}) ${exchange}-${subscriber}`,
`${countryCode}.${areaCode}.${exchange}.${subscriber}`,
`${areaCode}-${exchange}-${subscriber}`
];
return randomChoice(formats);
}
// Generate international phone
function generateInternationalPhone() {
const countries = [
{ code: '+1', length: 10 }, // US/Canada
{ code: '+44', length: 10 }, // UK
{ code: '+49', length: 11 }, // Germany
{ code: '+33', length: 9 } // France
];
const country = randomChoice(countries);
const number = Array.from({ length: country.length }, () =>
randomInt(0, 9)
).join('');
return `${country.code} ${number}`;
}
console.log(generateEmail('john.doe'));
console.log(generatePhone());
console.log(generateInternationalPhone()); // Generate addresses
const STREETS = ['Main', 'Oak', 'Maple', 'Cedar', 'Pine', 'Elm'];
const STREET_TYPES = ['St', 'Ave', 'Rd', 'Blvd', 'Ln', 'Dr'];
const CITIES = ['New York', 'Los Angeles', 'Chicago', 'Houston', 'Phoenix'];
const STATES = ['NY', 'CA', 'IL', 'TX', 'AZ', 'FL', 'PA', 'OH'];
function generateAddress() {
return {
street: `${randomInt(1, 9999)} ${randomChoice(STREETS)} ${randomChoice(STREET_TYPES)}`,
apartment: Math.random() > 0.5 ? `Apt ${randomInt(1, 999)}` : null,
city: randomChoice(CITIES),
state: randomChoice(STATES),
zipCode: String(randomInt(10000, 99999)),
country: 'USA'
};
}
// Generate coordinates
function generateCoordinates(centerLat = 0, centerLng = 0, radius = 10) {
const radiusInDegrees = radius / 111; // Approximate km to degrees
const u = Math.random();
const v = Math.random();
const w = radiusInDegrees * Math.sqrt(u);
const t = 2 * Math.PI * v;
const lat = centerLat + (w * Math.cos(t));
const lng = centerLng + (w * Math.sin(t));
return {
latitude: parseFloat(lat.toFixed(6)),
longitude: parseFloat(lng.toFixed(6))
};
}
// Generate within city bounds
function generateCityCoordinates(city) {
const cityBounds = {
'New York': { lat: 40.7128, lng: -74.0060 },
'Los Angeles': { lat: 34.0522, lng: -118.2437 },
'Chicago': { lat: 41.8781, lng: -87.6298 }
};
const center = cityBounds[city] || { lat: 0, lng: 0 };
return generateCoordinates(center.lat, center.lng, 20);
}
console.log(generateAddress());
console.log(generateCoordinates(40.7128, -74.0060, 5)); // E-commerce test data
const CATEGORIES = ['Electronics', 'Clothing', 'Books', 'Home', 'Sports'];
const BRANDS = ['BrandA', 'BrandB', 'BrandC', 'Generic'];
const COLORS = ['Red', 'Blue', 'Green', 'Black', 'White'];
function generateProduct() {
const category = randomChoice(CATEGORIES);
const basePrice = randomFloat(9.99, 999.99, 2);
return {
id: crypto.randomUUID(),
sku: `SKU-${randomString(8, 'uppercase')}`,
name: generateProductName(category),
description: `A great ${category.toLowerCase()} product`,
category,
brand: randomChoice(BRANDS),
price: basePrice,
salePrice: Math.random() > 0.7 ? randomFloat(basePrice * 0.5, basePrice * 0.9, 2) : null,
currency: 'USD',
inStock: Math.random() > 0.1,
quantity: randomInt(0, 1000),
weight: randomFloat(0.1, 50, 2),
dimensions: {
length: randomFloat(1, 100, 1),
width: randomFloat(1, 100, 1),
height: randomFloat(1, 100, 1),
unit: 'cm'
},
colors: Array.from({ length: randomInt(1, 3) }, () =>
randomChoice(COLORS)
),
rating: randomFloat(1, 5, 1),
reviews: randomInt(0, 10000),
createdAt: randomPastDate(730),
updatedAt: randomPastDate(30)
};
}
function generateProductName(category) {
const adjectives = ['Premium', 'Professional', 'Deluxe', 'Essential'];
const nouns = {
'Electronics': ['Gadget', 'Device', 'Tool'],
'Clothing': ['Shirt', 'Pants', 'Jacket'],
'Books': ['Guide', 'Manual', 'Novel'],
'Home': ['Decor', 'Furniture', 'Appliance'],
'Sports': ['Equipment', 'Gear', 'Accessory']
};
return `${randomChoice(adjectives)} ${randomChoice(nouns[category] || ['Item'])}`;
}
function generateOrder() {
const items = Array.from({ length: randomInt(1, 5) }, () => ({
productId: crypto.randomUUID(),
quantity: randomInt(1, 5),
price: randomFloat(9.99, 199.99, 2)
}));
const subtotal = items.reduce((sum, item) =>
sum + (item.price * item.quantity), 0
);
const tax = subtotal * 0.08;
const shipping = randomFloat(5, 20, 2);
return {
id: crypto.randomUUID(),
orderNumber: `ORD-${randomInt(100000, 999999)}`,
customerId: crypto.randomUUID(),
items,
subtotal: parseFloat(subtotal.toFixed(2)),
tax: parseFloat(tax.toFixed(2)),
shipping,
total: parseFloat((subtotal + tax + shipping).toFixed(2)),
status: randomChoice(['pending', 'processing', 'shipped', 'delivered']),
paymentMethod: randomChoice(['credit_card', 'paypal', 'bank_transfer']),
shippingAddress: generateAddress(),
createdAt: randomPastDate(90),
deliveredAt: Math.random() > 0.3 ? randomPastDate(30) : null
};
}
console.log(JSON.stringify(generateProduct(), null, 2)); // Jest/Vitest with random data
import { describe, it, expect, beforeEach } from 'vitest';
describe('User service', () => {
let testUser;
beforeEach(() => {
// Generate fresh random user for each test
testUser = generateRandomUser();
});
it('should create user with valid email', () => {
expect(testUser.email).toMatch(/^[^\s@]+@[^\s@]+\.[^\s@]+$/);
});
it('should generate unique IDs', () => {
const users = Array.from({ length: 100 }, generateRandomUser);
const ids = new Set(users.map(u => u.id));
expect(ids.size).toBe(100); // All unique
});
it('should handle edge cases', () => {
// Test with specific random data
const edgeCases = [
generateRandomUser({ age: 0 }),
generateRandomUser({ age: 150 }),
generateRandomUser({ name: '' }),
generateRandomUser({ name: 'a'.repeat(1000) })
];
edgeCases.forEach(user => {
expect(() => validateUser(user)).not.toThrow();
});
});
});
// Seeded tests for reproducibility
describe('Seeded random tests', () => {
it('generates same data with same seed', () => {
const rng1 = new SeededRandom(42);
const rng2 = new SeededRandom(42);
const data1 = generateTestData(rng1, 100);
const data2 = generateTestData(rng2, 100);
expect(data1).toEqual(data2);
});
}); // Property-based testing with fast-check
import fc from 'fast-check';
describe('String utilities', () => {
it('reversing twice returns original', () => {
fc.assert(
fc.property(fc.string(), (str) => {
expect(reverse(reverse(str))).toBe(str);
})
);
});
it('concatenation length equals sum', () => {
fc.assert(
fc.property(fc.string(), fc.string(), (s1, s2) => {
expect((s1 + s2).length).toBe(s1.length + s2.length);
})
);
});
});
// Custom generators
const userGenerator = fc.record({
id: fc.uuid(),
username: fc.string({ minLength: 3, maxLength: 20 }),
email: fc.emailAddress(),
age: fc.integer({ min: 18, max: 120 }),
active: fc.boolean()
});
describe('User validation', () => {
it('validates all generated users', () => {
fc.assert(
fc.property(userGenerator, (user) => {
expect(validateUser(user)).toBe(true);
})
);
});
});
// Complex data generation
const productGenerator = fc.record({
id: fc.uuid(),
name: fc.string({ minLength: 1, maxLength: 100 }),
price: fc.double({ min: 0.01, max: 9999.99, noNaN: true }),
inStock: fc.boolean(),
tags: fc.array(fc.string(), { maxLength: 5 })
}); // Fuzzing with random data
function fuzzTest(targetFunction, iterations = 1000) {
const failures = [];
for (let i = 0; i < iterations; i++) {
const input = generateFuzzInput();
try {
targetFunction(input);
} catch (error) {
failures.push({
iteration: i,
input,
error: error.message
});
}
}
return {
total: iterations,
failures: failures.length,
failureRate: (failures.length / iterations * 100).toFixed(2) + '%',
examples: failures.slice(0, 10)
};
}
function generateFuzzInput() {
const generators = [
() => '', // Empty string
() => ' '.repeat(randomInt(1, 1000)), // Whitespace
() => randomString(randomInt(0, 10000)), // Random length
() => '\x00\xFF\uFFFD', // Special chars
() => null, // Null
() => undefined, // Undefined
() => randomInt(-1000000, 1000000), // Numbers
() => ({})randomObject(), // Objects
() => [], // Empty array
() => Array(1000).fill('x') // Large array
];
return randomChoice(generators)();
}
// Fuzz API endpoints
async function fuzzAPI(endpoint, method = 'POST') {
const results = [];
for (let i = 0; i < 100; i++) {
const payload = generateRandomJSON();
try {
const response = await fetch(endpoint, {
method,
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
results.push({
status: response.status,
payload
});
} catch (error) {
results.push({
error: error.message,
payload
});
}
}
return results;
} // Snapshot testing with seeded random data
describe('Report generation', () => {
it('generates consistent report with seed', () => {
// Use fixed seed for snapshot testing
const SEED = 12345;
const rng = new SeededRandom(SEED);
const report = generateReport(rng);
// Snapshot will be consistent across test runs
expect(report).toMatchSnapshot();
});
it('updates snapshot when seed changes', () => {
// Different seed = different data = new snapshot
const SEED = 67890;
const rng = new SeededRandom(SEED);
const report = generateReport(rng);
expect(report).toMatchSnapshot();
});
});
// Generate deterministic test fixtures
function generateFixtures(seed = 42) {
const rng = new SeededRandom(seed);
return {
users: Array.from({ length: 10 }, () => generateUser(rng)),
products: Array.from({ length: 20 }, () => generateProduct(rng)),
orders: Array.from({ length: 50 }, () => generateOrder(rng))
};
}
// Save fixtures to file
const fixtures = generateFixtures(12345);
fs.writeFileSync('fixtures.json', JSON.stringify(fixtures, null, 2));
// Load in tests
const testData = JSON.parse(fs.readFileSync('fixtures.json')); // Generate edge case test data
function generateEdgeCases() {
return {
strings: [
'', // Empty
' ', // Single space
'\n', // Newline
'\t', // Tab
' '.repeat(10000), // Very long whitespace
'a'.repeat(10000), // Very long string
'👨👩👧👦', // Complex emoji
'\x00', // Null byte
'<script>alert("xss")</script>', // XSS attempt
'../../../etc/passwd', // Path traversal
"'; DROP TABLE users; --" // SQL injection
],
numbers: [
0,
-0,
1,
-1,
Number.MAX_SAFE_INTEGER,
Number.MIN_SAFE_INTEGER,
Number.MAX_VALUE,
Number.MIN_VALUE,
Infinity,
-Infinity,
NaN
],
arrays: [
[],
[null],
[undefined],
Array(10000).fill(0), // Large array
[[[[[[]]]]]] // Deep nesting
],
objects: [
{},
{ __proto__: null },
{ toString: () => 'evil' },
Object.create(null)
],
dates: [
new Date(0), // Unix epoch
new Date('1970-01-01'),
new Date('2038-01-19'), // Y2K38
new Date('invalid'), // Invalid date
new Date(8640000000000000), // Max date
new Date(-8640000000000000) // Min date
]
};
}
// Test with all edge cases
describe('Edge case testing', () => {
const edgeCases = generateEdgeCases();
it('handles edge case strings', () => {
edgeCases.strings.forEach(str => {
expect(() => processString(str)).not.toThrow();
});
});
it('handles edge case numbers', () => {
edgeCases.numbers.forEach(num => {
expect(() => processNumber(num)).not.toThrow();
});
});
}); // Validate generated random data
function validateGeneratedData(data, schema) {
const errors = [];
for (const [key, rules] of Object.entries(schema)) {
const value = data[key];
// Required check
if (rules.required && (value === null || value === undefined)) {
errors.push(`${key} is required`);
continue;
}
// Type check
if (rules.type && typeof value !== rules.type) {
errors.push(`${key} must be ${rules.type}`);
}
// Range checks
if (rules.min !== undefined && value < rules.min) {
errors.push(`${key} must be >= ${rules.min}`);
}
if (rules.max !== undefined && value > rules.max) {
errors.push(`${key} must be <= ${rules.max}`);
}
// Length checks
if (rules.minLength && value.length < rules.minLength) {
errors.push(`${key} length must be >= ${rules.minLength}`);
}
if (rules.maxLength && value.length > rules.maxLength) {
errors.push(`${key} length must be <= ${rules.maxLength}`);
}
// Pattern check
if (rules.pattern && !rules.pattern.test(value)) {
errors.push(`${key} must match pattern`);
}
// Enum check
if (rules.enum && !rules.enum.includes(value)) {
errors.push(`${key} must be one of: ${rules.enum.join(', ')}`);
}
}
return {
valid: errors.length === 0,
errors
};
}
// Example usage
const userSchema = {
id: { required: true, type: 'string', pattern: /^[a-f0-9-]{36}$/ },
username: { required: true, type: 'string', minLength: 3, maxLength: 20 },
age: { required: true, type: 'number', min: 0, max: 150 },
role: { required: true, type: 'string', enum: ['admin', 'user', 'guest'] }
};
const user = generateRandomUser();
const validation = validateGeneratedData(user, userSchema);
if (!validation.valid) {
console.error('Validation errors:', validation.errors);
} // Security considerations for random data
const crypto = require('crypto');
// ✅ SECURE: Cryptographic random for tokens
function generateSecureToken(bytes = 32) {
return crypto.randomBytes(bytes).toString('base64url');
}
// ✅ SECURE: Session ID generation
function generateSessionId() {
return crypto.randomBytes(32).toString('hex');
}
// ✅ SECURE: API key generation
function generateApiKey() {
const prefix = 'sk_';
const random = crypto.randomBytes(32).toString('base64url');
return prefix + random;
}
// ❌ INSECURE: Don't use Math.random() for security
function insecureToken() {
return Math.random().toString(36).substring(2);
}
// ✅ SECURE: Password generation
function generateSecurePassword(length = 16) {
const lowercase = 'abcdefghijklmnopqrstuvwxyz';
const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
const digits = '0123456789';
const symbols = '!@#$%^&*()_+-=[]{}|;:,.<>?';
const all = lowercase + uppercase + digits + symbols;
const bytes = crypto.randomBytes(length);
let password = '';
// Ensure at least one of each type
password += lowercase[bytes[0] % lowercase.length];
password += uppercase[bytes[1] % uppercase.length];
password += digits[bytes[2] % digits.length];
password += symbols[bytes[3] % symbols.length];
// Fill rest
for (let i = 4; i < length; i++) {
password += all[bytes[i] % all.length];
}
// Shuffle
const shuffled = password.split('').sort(() =>
crypto.randomBytes(1)[0] - 128
);
return shuffled.join('');
}
// Security checklist:
// ✓ Use crypto.randomBytes() for security tokens
// ✓ Use sufficient entropy (32 bytes minimum for tokens)
// ✓ Never use Math.random() for security
// ✓ Validate generated data before use
// ✓ Use HTTPS when transmitting tokens
// ✓ Store tokens securely (hashed, encrypted)