Hardware Random Number Generation

Hardware random number generation using /dev/random, /dev/urandom, and hardware RNG sources.


Linux Random Devices

/dev/random vs /dev/urandom

 1# /dev/random - Blocks when entropy pool is depleted
 2# Use for: Long-term cryptographic keys
 3
 4# /dev/urandom - Never blocks, uses CSPRNG when entropy low
 5# Use for: Most cryptographic operations (recommended)
 6
 7# Read random bytes
 8head -c 32 /dev/urandom | base64
 9
10# Generate random number
11od -An -N4 -tu4 < /dev/urandom
12
13# Generate random hex
14xxd -l 16 -p /dev/urandom

Check Entropy

 1# Available entropy
 2cat /proc/sys/kernel/random/entropy_avail
 3
 4# Should be > 1000 for good randomness
 5# Typical range: 128 - 4096
 6
 7# Watch entropy
 8watch -n 1 cat /proc/sys/kernel/random/entropy_avail
 9
10# Entropy pool size
11cat /proc/sys/kernel/random/poolsize

Hardware RNG (HRNG)

Check for Hardware RNG

 1# List hardware RNG devices
 2ls -l /dev/hwrng
 3
 4# Check if rng-tools is installed
 5which rngd
 6
 7# Install rng-tools
 8sudo apt install rng-tools
 9
10# Check RNG status
11sudo rngd -l
12
13# Start rng daemon
14sudo systemctl start rng-tools
15sudo systemctl enable rng-tools
16
17# Verify it's feeding entropy
18cat /proc/sys/kernel/random/entropy_avail
19# Should be consistently high (3000-4000)

CPU-based RNG (RDRAND/RDSEED)

1# Check if CPU supports RDRAND
2grep -o 'rdrand' /proc/cpuinfo
3
4# Check if CPU supports RDSEED
5grep -o 'rdseed' /proc/cpuinfo
6
7# Use CPU RNG with rng-tools
8sudo rngd -r /dev/hwrng

Generate Random Data

Random Bytes

 1# 32 random bytes
 2head -c 32 /dev/urandom
 3
 4# Random bytes as hex
 5xxd -l 32 -p /dev/urandom
 6
 7# Random bytes as base64
 8head -c 32 /dev/urandom | base64
 9
10# Random bytes to file
11dd if=/dev/urandom of=random.bin bs=1M count=10

Random Numbers

 1# Random number (0-99)
 2shuf -i 0-99 -n 1
 3
 4# Random number using /dev/urandom
 5echo $(($(od -An -N4 -tu4 < /dev/urandom) % 100))
 6
 7# Multiple random numbers
 8shuf -i 1-100 -n 10
 9
10# Random float (0-1)
11echo "scale=10; $(od -An -N4 -tu4 < /dev/urandom) / 4294967295" | bc -l

Random Strings

 1# Random alphanumeric string (32 chars)
 2tr -dc A-Za-z0-9 </dev/urandom | head -c 32
 3
 4# Random password (with special chars)
 5tr -dc 'A-Za-z0-9!@#$%^&*' </dev/urandom | head -c 20
 6
 7# Random UUID
 8cat /proc/sys/kernel/random/uuid
 9
10# Or use uuidgen
11uuidgen

Python

 1import os
 2import secrets
 3
 4# Cryptographically secure random bytes
 5random_bytes = os.urandom(32)
 6print(random_bytes.hex())
 7
 8# Using secrets module (Python 3.6+)
 9# Token (URL-safe)
10token = secrets.token_urlsafe(32)
11print(token)
12
13# Token (hex)
14token_hex = secrets.token_hex(16)
15print(token_hex)
16
17# Random number
18random_num = secrets.randbelow(100)  # 0-99
19print(random_num)
20
21# Random choice
22items = ['apple', 'banana', 'cherry']
23choice = secrets.choice(items)
24print(choice)
25
26# Generate password
27import string
28alphabet = string.ascii_letters + string.digits + string.punctuation
29password = ''.join(secrets.choice(alphabet) for i in range(20))
30print(password)

Go

 1package main
 2
 3import (
 4    "crypto/rand"
 5    "encoding/base64"
 6    "encoding/hex"
 7    "fmt"
 8    "math/big"
 9)
10
11func main() {
12    // Random bytes
13    bytes := make([]byte, 32)
14    _, err := rand.Read(bytes)
15    if err != nil {
16        panic(err)
17    }
18    
19    // As hex
20    fmt.Println("Hex:", hex.EncodeToString(bytes))
21    
22    // As base64
23    fmt.Println("Base64:", base64.StdEncoding.EncodeToString(bytes))
24    
25    // Random number (0-99)
26    n, err := rand.Int(rand.Reader, big.NewInt(100))
27    if err != nil {
28        panic(err)
29    }
30    fmt.Println("Random number:", n)
31    
32    // Random string
33    const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
34    b := make([]byte, 32)
35    for i := range b {
36        num, _ := rand.Int(rand.Reader, big.NewInt(int64(len(letters))))
37        b[i] = letters[num.Int64()]
38    }
39    fmt.Println("Random string:", string(b))
40}

Rust

 1use rand::{Rng, thread_rng};
 2use rand::distributions::Alphanumeric;
 3
 4fn main() {
 5    let mut rng = thread_rng();
 6    
 7    // Random number
 8    let n: u32 = rng.gen();
 9    println!("Random u32: {}", n);
10    
11    // Random number in range
12    let n: u32 = rng.gen_range(0..100);
13    println!("Random 0-99: {}", n);
14    
15    // Random bytes
16    let mut bytes = [0u8; 32];
17    rng.fill(&mut bytes);
18    println!("Random bytes: {:?}", bytes);
19    
20    // Random string
21    let s: String = thread_rng()
22        .sample_iter(&Alphanumeric)
23        .take(32)
24        .map(char::from)
25        .collect();
26    println!("Random string: {}", s);
27}

OpenSSL

 1# Random bytes
 2openssl rand 32
 3
 4# Random bytes as hex
 5openssl rand -hex 32
 6
 7# Random bytes as base64
 8openssl rand -base64 32
 9
10# Random password
11openssl rand -base64 20 | tr -d "=+/" | cut -c1-20

Testing Randomness

NIST Statistical Test Suite

 1# Install sts (NIST Statistical Test Suite)
 2# Download from: https://csrc.nist.gov/projects/random-bit-generation/documentation-and-software
 3
 4# Generate test data
 5head -c 1000000 /dev/urandom > random.bin
 6
 7# Run tests
 8./assess 1000000
 9
10# Good randomness should pass most tests

Simple Chi-Square Test

1# Generate random numbers and check distribution
2for i in {1..10000}; do 
3    echo $(($(od -An -N1 -tu1 < /dev/urandom) % 10))
4done | sort | uniq -c
5
6# Each digit should appear ~1000 times

Increase Entropy (if needed)

haveged

1# Install haveged (entropy daemon)
2sudo apt install haveged
3
4# Start service
5sudo systemctl start haveged
6sudo systemctl enable haveged
7
8# Check entropy (should be consistently high)
9cat /proc/sys/kernel/random/entropy_avail

rng-tools with RDRAND

1# Use CPU's RDRAND instruction
2sudo rngd -r /dev/hwrng
3
4# Or configure in /etc/default/rng-tools
5HRNGDEVICE=/dev/hwrng

Windows

 1# PowerShell random number
 2Get-Random -Minimum 0 -Maximum 100
 3
 4# Random bytes (using .NET)
 5$bytes = New-Object byte[] 32
 6$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::new()
 7$rng.GetBytes($bytes)
 8[Convert]::ToBase64String($bytes)
 9
10# Random GUID
11[guid]::NewGuid()
12
13# Random password
14Add-Type -AssemblyName System.Web
15[System.Web.Security.Membership]::GeneratePassword(20, 5)

Best Practices

  1. Use /dev/urandom for most applications (not /dev/random)
  2. Use secrets module in Python (not random module)
  3. Use crypto/rand in Go (not math/rand)
  4. Check entropy on headless servers
  5. Use hardware RNG when available
  6. Never seed with time for cryptographic purposes
  7. Use OS-provided RNG (don't roll your own)

Related Snippets