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)
|
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.