# Java Random Number Generation with Random and SecureRandom

> Generate random numbers in Java using Random for general use and SecureRandom for cryptographic needs, with range examples and performance benchmarks

**URL:** https://sentry.io/answers/generating-random-numbers-in-java/

---

## The Problem

How do I generate random numbers in a specific range in Java?

## The Solution

In modern versions of Java, the `nextInt` method from `java.util.Random` can be used to create a random number generator.

```java
import java.util.Random;

public class RandomDemo{
    public static void main(String[] args){

        Random rand = new Random();
        int n = rand.nextInt(2);
        System.out.println(n);
    }
}
```

This method will generate a random number between `0` and the specified number (**including** `0` and **excluding** the number specified).

* In the above code, `2` is specified as the argument, so it will always output `0` or `1`.
* The `nextInt` method can also be called without an argument, causing it to return any valid integer (including negative integers).

To generate a random number in a range between a given `start` and `end` number:

* Use **(end - start + 1)** as the input (adding 1 makes the end inclusive).
* Add **start** to the result.

For example, the following code returns a random number between `-5` and `5` (inclusive):

```java
import java.util.Random;

public class RandRange{
    public static void main(String[] args){

        int start = -5;
        int end = 5;
        Random rand = new Random();
        int n = rand.nextInt(end - start + 1) + start;
        System.out.println(n);
    }
}
```

### Generate Secure Random Numbers in Java

The `nextInt` method generates pseudorandom numbers that aren't suitable for cases requiring secure random numbers that can't easily be predicted. In such cases, it's better to use the `SecureRandom` class to generate a secure random number.

Consider the following example:

```java
import java.security.SecureRandom;

public class SecureDemo{
    public static void main(String[] args) {

        SecureRandom secureRandom = new SecureRandom();
        int n = secureRandom.nextInt(2);
        System.out.println(n);
    }
}
```

This code has the same functionality as the first example. It will always output either `0` or `1`.

While the name of the function is `SecureRandom`, simply calling it doesn't guarantee a non-deterministic output. The underlying implementation dictates whether or not the output is truly non-deterministic.

The [official `SecureRandom` documentation](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/security/SecureRandom.html) states:

> Many `SecureRandom` implementations are in the form of a pseudo-random number generator (PRNG, also known as deterministic random bits generator or DRBG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a random seed. Other implementations may produce true random numbers, and yet others may use a combination of both techniques.

Multiple factors influence whether the use of `SecureRandom` rather than `Random` will be enough to meet the security requirements of a program, such as:

* The hardware the code is running on.
* The operating system being used.

### SecureRandom vs. Random Timing in Java

The following benchmarking script is used to assess and compare the speed of `Random` and `SecureRandom` in Java by running both versions one hundred million times:

```java
import java.util.Random;
import java.security.SecureRandom;

public class RandomBenchmark {
    public static void main(String[] args) {
        final int ITERATIONS = 100000000;

        // Benchmark java.util.Random
        Random random = new Random();
        long startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            random.nextInt();
        }
        long endTime = System.nanoTime();
        long durationRandom = endTime - startTime;
        System.out.println("java.util.Random duration: " + (double)durationRandom/1000000000 + " seconds");

        // Benchmark java.security.SecureRandom
        SecureRandom secureRandom = new SecureRandom();
        startTime = System.nanoTime();
        for (int i = 0; i < ITERATIONS; i++) {
            secureRandom.nextInt();
        }
        endTime = System.nanoTime();
        long durationSecureRandom = endTime - startTime;
        System.out.println("java.security.SecureRandom duration: " + (double)durationSecureRandom/1000000000 + " seconds");
        System.out.println("----");
        System.out.println("SecureRandom is " + (double)durationSecureRandom / durationRandom + " times slower than Random");
    }
}
```

On an M1-Max MacBook Pro, this script outputs:

```
java.util.Random duration: 0.785196917 seconds
java.security.SecureRandom duration: 5.760956292 seconds
----
SecureRandom is 7.336957350788987 times slower than Random
```

This shows that `SecureRandom` is significantly slower than `Random`, making `Random` the more desirable choice for generating multiple numbers when predictable or deterministic outputs are permissible.

---

*Source: [sentry.io/answers/generating-random-numbers-in-java/](https://sentry.io/answers/generating-random-numbers-in-java/)*
