# 5 Secure Ways to Generate Random Numbers in Python

Rate this post

π‘ Problem Formulation: When building applications, especially ones dealing with security and cryptography, there’s often a need for truly unpredictable random numbers. For instance, an application may require a cryptographically secure random token as a password reset link. Using Python’s built-in modules, developers can generate random numbers that are suitable for security-sensitive applications.

## Method 1: Using the `secrets` Module

The `secrets` module is designed for generating cryptographically strong random numbers suitable for managing data such as passwords, account authentication, security tokens, and related secrets. It’s included in Python’s standard library and is an easy-to-use solution for most security needs.

Here’s an example:

```import secrets

# Generate a secure random number between 0 and 99
secure_num = secrets.randbelow(100)
print(secure_num)```

Output: 42 (Note: Output will vary every time you run it)

This code snippet imports the `secrets` module and then generates a secure random number between 0 and 99. The `secrets.randbelow(100)` function provides a random number that is less than the provided upper bound, suitable for any application needing an unpredictable result.

## Method 2: Using the `os.urandom` Function

The `os` module’s `urandom` function returns a string of random bytes from an OS-specific randomness source. This source is typically suitable for cryptographic use, making the produced bytes unpredictable and secure.

Here’s an example:

```import os

# Get 16 bytes of secure random data
random_bytes = os.urandom(16)
print(random_bytes)```

Output: b’\xebr\x1d\xe0\x03S\xd5\x9fL\xbd\xd2<\x1e\x85\xed\xd6'

In this example, we import the `os` library and use the `os.urandom` function to generate 16 bytes of secure random data. The output is displayed as a byte string, with each byte represented by an escaped sequence suitable for cryptographic operations.

## Method 3: Using the `random.SystemRandom` Class

The `random` module’s `SystemRandom` class uses sources provided by the operating system to generate random numbers. This class provides the same interface as `random.Random`, but uses `os.urandom` to generate the underlying random numbers, making it cryptographically safe.

Here’s an example:

```import random

# Create a SystemRandom instance
system_random = random.SystemRandom()

# Use the instance to generate a secure random floating point between 0 and 1
secure_float = system_random.random()
print(secure_float)```

Output: 0.41907358279680914 (Note: Output will vary every time you run it)

The code creates an instance of `random.SystemRandom` which taps into the underlying OS’s secure random number generator. We then generate a secure random floating-point number between 0 and 1. This is useful when floating-point precision is required!

## Method 4: Using `numpy` with `random.SystemRandom`

While not a part of the standard library, the `numpy` library can be used alongside `random.SystemRandom` to generate arrays of secure random numbers efficiently, which can be useful in scientific computing that also requires secure randomness.

Here’s an example:

```import numpy as np
import random

# Create a SystemRandom instance
system_random = random.SystemRandom()

# Use the instance to generate a secure random array
secure_array = np.array([system_random.random() for _ in range(10)])
print(secure_array)```

Output: [0.27643876, 0.80126587, …, 0.78321354] (Note: Output will vary every time you run it)

This snippet uses a list comprehension to generate a list of secure random numbers, then converts it to a `numpy` array. This approach combines the cryptographic strength of `random.SystemRandom` with the array-manipulation capabilities of `numpy`.

## Bonus One-Liner Method 5: Generating a Secure Random Integer with `secrets`

For a quick and easy way to generate a secure random integer within a specified range, you can use a one-liner that leverages the `secrets` module.

Here’s an example:

```import secrets

# One-liner to generate a random integer from 0 to 99999
secure_rand_int = secrets.randbelow(100000)
print(secure_rand_int)```

Output: 42517 (Note: Output will vary every time you run it)

The above code is efficient for generating an integer within a specified range, using `secrets.randbelow` to produce a secure random number. It’s particularly handy when an application requires a unique identifier or nonce that’s also secure.

## Summary/Discussion

• Method 1: `secrets` Module. Easy to use for most security-related needs. Limited to basic functionality provided by the module.
• Method 2: `os.urandom` Function. Generates a string of secure random bytes suitable for cryptographic use. Requires additional steps to convert bytes into other numeric types.
• Method 3: `random.SystemRandom` Class. Cryptographically secure version of `random.Random`, offering versatile random number generation. Not as straightforward or optimized for array generation.
• Method 4: `numpy` with `random.SystemRandom`. Efficient generation of secure random number arrays but requires an external library.
• Bonus Method 5: `secrets` for Random Integers. Quick one-liner for generating secure random integers within a range. Simplicity may be a limiting factor for more complex tasks.