Java SecureRandom
Last modified: July 16, 2026
This Java SecureRandom tutorial shows how to generate cryptographically secure
random numbers in Java using the SecureRandom class. We cover
generating random integers, doubles, byte arrays, seeds, and cryptographic
keys.
SecureRandom
SecureRandom is a Java class that generates cryptographically
strong random numbers. Unlike java.util.Random, which uses a
linear congruential formula, SecureRandom employs a
cryptographically strong pseudo-random number generator (CSPRNG). It gathers
entropy from the underlying operating system (e.g., /dev/random
and /dev/urandom on Unix-like systems) to produce unpredictable
outputs suitable for security-sensitive applications.
The key methods of SecureRandom are:
| Method | Description |
|---|---|
nextInt() |
Returns a uniformly distributed integer. |
nextInt(int bound) |
Returns an integer between 0 (inclusive) and bound (exclusive). |
nextDouble() |
Returns a double between 0.0 (inclusive) and 1.0 (exclusive). |
nextBytes(byte[]) |
Fills a byte array with random bytes. |
getInstance(String algorithm) |
Creates a SecureRandom instance with a specific algorithm. |
setSeed(byte[]) |
Seeds (or reseeds) the random generator. |
generateSeed(int) |
Returns a seed byte array from system entropy. |
Generating random integers and doubles
The following example shows basic SecureRandom usage to generate
random integers, doubles, and byte arrays.
import java.security.SecureRandom;
void main() {
SecureRandom sr = new SecureRandom();
int ri = sr.nextInt();
System.out.println("Random int: " + ri);
int ri2 = sr.nextInt(100);
System.out.println("Random int (0-99): " + ri2);
double rd = sr.nextDouble();
System.out.println("Random double: " + rd);
byte[] data = new byte[6];
sr.nextBytes(data);
System.out.print("Random bytes: ");
for (byte b : data) {
System.out.printf("%02x ", b);
}
System.out.println();
}
The example creates a SecureRandom instance and calls its basic
methods. The nextInt method returns a random integer; the
nextInt(100) returns a value between 0 and 99. The
nextDouble returns a double between 0.0 and 1.0, and
nextBytes fills a byte array with random values.
Generating numbers in a range
The following program generates random integers and doubles within a specific range.
import java.security.SecureRandom;
void main() {
SecureRandom sr = new SecureRandom();
int min = 10;
int max = 20;
int ri = sr.nextInt(max - min + 1) + min;
System.out.printf("Random int (%d-%d): %d%n", min, max, ri);
double rd = min + (max - min) * sr.nextDouble();
System.out.printf("Random double (%d-%d): %.2f%n", min, max, rd);
}
int ri = sr.nextInt(max - min + 1) + min;
An integer in a closed interval [min, max] is produced by
calculating the range size (max - min + 1), generating a value
from 0 to that size, and shifting by min.
double rd = min + (max - min) * sr.nextDouble();
A double in a half-open interval [min, max) is created by
scaling nextDouble by the range width and adding the minimum.
Generating secure random strings
The following example creates secure random strings from a character alphabet. Secure random strings are used for session identifiers, API tokens, and temporary passwords.
import java.security.SecureRandom;
void main() {
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var sr = new SecureRandom();
var token1 = new StringBuilder(8);
for (int i = 0; i < 8; i++) {
token1.append(alphabet.charAt(sr.nextInt(alphabet.length())));
}
System.out.println("Token (8 chars): " + token1);
var token2 = new StringBuilder(16);
for (int i = 0; i < 16; i++) {
token2.append(alphabet.charAt(sr.nextInt(alphabet.length())));
}
System.out.println("Token (16 chars): " + token2);
}
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
We define a character set containing upper-case letters, lower-case letters, and digits—62 characters in total.
token1.append(alphabet.charAt(sr.nextInt(alphabet.length())));
Inside the loop, we use sr.nextInt(alphabet.length()) to pick a
random index into the alphabet and append the character at that index to a
StringBuilder.
$ java Main.java Token (8 chars): a3Fg7K2x Token (16 chars): B9mQ4rX8tL2pZw5N
Using specific algorithms
SecureRandom supports different algorithms via the
getInstance factory method. Common algorithms include
SHA1PRNG (a Java-built-in PRNG using SHA-1) and
NativePRNG (which reads from the OS entropy source).
import java.security.SecureRandom;
import java.security.NoSuchAlgorithmException;
void main() {
try {
SecureRandom sr1 = SecureRandom.getInstance("SHA1PRNG");
System.out.println("SHA1PRNG int: " + sr1.nextInt());
SecureRandom sr2 = SecureRandom.getInstance("NativePRNG");
System.out.println("NativePRNG int: " + sr2.nextInt());
} catch (NoSuchAlgorithmException e) {
System.err.println("Algorithm not available: " + e.getMessage());
}
}
The example requests specific algorithms via
SecureRandom.getInstance. Not all algorithms are available on
every platform; a NoSuchAlgorithmException is thrown if the
requested algorithm is not present.
Seeding SecureRandom
By default, SecureRandom self-seeds from system entropy. However,
we can seed it manually with setSeed to produce reproducible
sequences, which is useful for testing.
import java.security.SecureRandom;
void main() {
byte[] seed = { 1, 2, 3, 4 };
SecureRandom sr1 = new SecureRandom();
sr1.setSeed(seed);
SecureRandom sr2 = new SecureRandom();
sr2.setSeed(seed);
System.out.println("sr1: " + sr1.nextInt());
System.out.println("sr2: " + sr2.nextInt());
}
Both instances are seeded with the same four bytes, so they produce identical output sequences. In production, manual seeding is discouraged because it reduces unpredictability.
$ java Main.java sr1: -1157522390 sr2: -1157522390
Generating seeds
The generateSeed method returns a seed byte array obtained
directly from system entropy, without affecting the internal state of the
SecureRandom instance.
import java.security.SecureRandom;
void main() {
SecureRandom sr = new SecureRandom();
byte[] seed = sr.generateSeed(16);
System.out.print("Generated seed: ");
for (byte b : seed) {
System.out.printf("%02x", b);
}
System.out.println();
}
The generateSeed method is useful when we need entropy for
initializing other cryptographic primitives without altering the state of our
main SecureRandom instance.
$ java Main.java Generated seed: 2f7a1b4c8e3d9f05a6c2b8e4d1f7093a
Generating cryptographic keys
A common use of SecureRandom is generating symmetric keys for
encryption algorithms such as AES. The following example creates 128-bit and
256-bit keys.
import java.security.SecureRandom;
import java.util.Base64;
void main() {
SecureRandom sr = new SecureRandom();
// 256-bit key
byte[] key256 = new byte[32];
sr.nextBytes(key256);
System.out.println("256-bit key (Base64): "
+ Base64.getEncoder().encodeToString(key256));
// 128-bit key
byte[] key128 = new byte[16];
sr.nextBytes(key128);
System.out.print("128-bit key (hex): ");
for (byte b : key128) {
System.out.printf("%02x", b);
}
System.out.println();
}
The example fills byte arrays of 32 and 16 bytes with cryptographically strong random values, suitable for AES-256 and AES-128 keys respectively. The keys are displayed in Base64 and hexadecimal formats.
Performance considerations
SecureRandom is significantly slower than Random
because it gathers entropy and uses cryptographic operations. The following
program compares the throughput of both classes.
import java.security.SecureRandom;
import java.util.Random;
void main() {
int count = 1_000_000;
long start = System.currentTimeMillis();
Random r = new Random();
for (int i = 0; i < count; i++) {
r.nextInt();
}
long dur1 = System.currentTimeMillis() - start;
System.out.println("Random: " + dur1 + " ms");
start = System.currentTimeMillis();
SecureRandom sr = new SecureRandom();
for (int i = 0; i < count; i++) {
sr.nextInt();
}
long dur2 = System.currentTimeMillis() - start;
System.out.println("SecureRandom: " + dur2 + " ms");
}
The program generates one million random integers with each class and measures the elapsed time.
$ java Main.java Random: 18 ms SecureRandom: 112 ms
SecureRandom should only be used when cryptographic security is
required. For non-sensitive tasks (simulations, games, shuffling), prefer
Random or ThreadLocalRandom.
Source
Java SecureRandom documentation
This tutorial covered the Java SecureRandom class. We have shown
how to generate random integers, doubles, byte arrays, tokens, seeds, and
cryptographic keys.
Author
List all Java tutorials.