Today I discovered the important distinctions between /dev/urandom and /dev/random, and their proper usage for secure random number generation.

Understanding Random Devices

Unix-like systems provide special devices for accessing random data from the kernel’s entropy pool:

/dev/random vs /dev/urandom:

/dev/random - “True” Random:

  • Blocks when entropy pool is empty
  • Provides cryptographically secure random data
  • Slower due to blocking behavior
  • Suitable for generating long-term keys

/dev/urandom - Pseudo-Random:

  • Never blocks (always returns data)
  • Uses cryptographically secure PRNG
  • Faster for most applications
  • Recommended for most use cases

Practical Usage Examples

Basic Random Data Generation:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Generate 16 bytes of random data
dd if=/dev/urandom bs=16 count=1 2>/dev/null | hexdump -C

# Generate random password
tr -cd '[:alnum:]' < /dev/urandom | head -c 32
# Output: K9mP2qR8vN4LaB3xJ7tY5wZ1cE6fH0sU

# Generate random UUID-like string
dd if=/dev/urandom bs=16 count=1 2>/dev/null | base64 | tr -d '=' | head -c 22
# Output: K9mP2qR8vN4LaB3xJ7tY5w

Cryptographic Applications:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Generate SSH key entropy
ssh-keygen -t rsa -b 4096 -f ~/.ssh/new_key -N ""
# (Uses /dev/urandom internally)

# Generate random salt for password hashing
openssl rand -base64 32
# Output: K9mP2qR8vN4LaB3xJ7tY5wZ1cE6fH0sUqV3mN8pR2tX=

# Create random initialization vector
dd if=/dev/urandom bs=16 count=1 2>/dev/null | base64
# Output: K9mP2qR8vN4LaB3xJ7tY5w==

System Administration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# Generate random MAC address
printf '%02x:%02x:%02x:%02x:%02x:%02x\n' \
  $(od -An -N6 -tu1 /dev/urandom | tr ' ' '\n' | grep -v '^$')
# Output: 4a:3f:2e:1d:5c:8b

# Create random temporary filenames
temp_file="/tmp/$(tr -cd '[:alnum:]' < /dev/urandom | head -c 16)"
echo "Random temp file: $temp_file"

# Generate random port numbers
random_port=$((RANDOM % 64512 + 1024))
echo "Random port: $random_port"

Programming Language Integration

Shell Scripting:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash

# Function to generate secure random string
generate_secure_random() {
    local length=${1:-32}
    local charset=${2:-'[:alnum:]'}
    
    tr -cd "$charset" < /dev/urandom | head -c "$length"
}

# Generate API key
api_key=$(generate_secure_random 64 '[:alnum:]')
echo "API Key: $api_key"

# Generate session token
session_token=$(generate_secure_random 32 '[:alnum:]')
echo "Session Token: $session_token"

# Generate random hex string
hex_string=$(dd if=/dev/urandom bs=16 count=1 2>/dev/null | xxd -p -c 32)
echo "Hex String: $hex_string"

Python Integration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
import os
import secrets
import base64

# Using os.urandom (preferred for cryptographic use)
random_bytes = os.urandom(32)
print(f"Random bytes: {random_bytes.hex()}")

# Using secrets module (Python 3.6+)
secure_token = secrets.token_urlsafe(32)
print(f"Secure token: {secure_token}")

# Generate cryptographically secure password
import string
alphabet = string.ascii_letters + string.digits + "!@#$%^&*"
password = ''.join(secrets.choice(alphabet) for _ in range(16))
print(f"Secure password: {password}")

# Random UUID
import uuid
random_uuid = uuid.uuid4()
print(f"Random UUID: {random_uuid}")

System Monitoring:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# Check available entropy
cat /proc/sys/kernel/random/entropy_avail
# Output: 3847 (bits of entropy available)

# Monitor entropy pool
watch -n 1 'cat /proc/sys/kernel/random/entropy_avail'

# Check random device statistics
cat /proc/sys/kernel/random/poolsize
cat /proc/sys/kernel/random/read_wakeup_threshold
cat /proc/sys/kernel/random/write_wakeup_threshold

Security Considerations

When to Use Each Device:

Use /dev/urandom for:

  • Session tokens and API keys
  • Password generation
  • Initialization vectors
  • Salts for password hashing
  • General cryptographic purposes

Use /dev/random for:

  • Long-term cryptographic keys
  • Certificate generation (rarely needed directly)
  • One-time pads
  • When you need maximum entropy guarantees

Best Practices:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# Good: Fast and secure for most uses
password=$(tr -cd '[:alnum:]' < /dev/urandom | head -c 20)

# Avoid: Slow and usually unnecessary
# password=$(tr -cd '[:alnum:]' < /dev/random | head -c 20)

# Good: Check if enough entropy is available
if [ $(cat /proc/sys/kernel/random/entropy_avail) -lt 100 ]; then
    echo "Warning: Low entropy available"
fi

# Good: Use appropriate tools
openssl rand -base64 32  # Uses /dev/urandom internally

Common Pitfalls:

1
2
3
4
5
6
7
8
# Bad: Predictable random data
password=$(date +%s | sha256sum | head -c 20)

# Bad: Using RANDOM for cryptographic purposes
session_id=$RANDOM$RANDOM$RANDOM

# Good: Cryptographically secure
session_id=$(tr -cd '[:alnum:]' < /dev/urandom | head -c 32)

Performance Comparison:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Benchmark random data generation
time dd if=/dev/urandom bs=1M count=10 of=/dev/null 2>/dev/null
# Typically: ~0.1-0.5 seconds

time dd if=/dev/random bs=1M count=10 of=/dev/null 2>/dev/null  
# May block indefinitely on low-entropy systems

# Test entropy depletion
dd if=/dev/random bs=1 count=1000 of=/dev/null
# Will likely block after some bytes

Understanding these random devices is crucial for implementing secure systems, as using the wrong source of randomness can compromise the security of cryptographic operations.