skip to content

SecureRandom API

SecureRandom is the CSPRNG you must use for keys, IVs, salts and tokens; java.util.Random and Math.random are predictable and unsafe here. Interviewers also ask about seeding, since a fixed seed makes the output deterministic.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

Why is java.util.Random (or Math.random()) unsafe for generating security values like tokens or keys, and what should you use instead?

level: juniorimportance: must knowfreq 78%

answer

  1. util.Random = 48-bit LCG, crackable from 2 outputs
  2. Math.random() is the same algorithm
  3. SecureRandom = CSPRNG seeded from OS entropy
  4. 'If it protects something, use SecureRandom'
  5. SecureRandom extends Random -> drop-in

basics

~10 s

java.util.Random and Math.random() are predictable: from a few outputs an attacker can compute the seed and predict all future values. For anything security-related (tokens, keys, salts) use java.security.SecureRandom, which is unpredictable.

solid answer

~40 s

java.util.Random is a linear congruential generator (LCG) with a 48-bit seed; given a couple of outputs an attacker can recover the internal state and predict every future and past value. Math.random() is backed by the same algorithm. That predictability is fatal for session tokens, password-reset tokens, API keys, salts, IVs, and nonces, because an attacker who predicts them can forge or guess them. The correct tool is java.security.SecureRandom, a cryptographically secure PRNG (CSPRNG): it is seeded from OS entropy and designed so that observing past outputs does not let you predict future ones. Rule of thumb: if the value protects something, use SecureRandom; java.util.Random is fine only for non-security uses like shuffling a game or sampling.

go deeper

for a junior

Knows the rule: use SecureRandom for tokens/keys/passwords, not Random or Math.random(), and that SecureRandom is built into the JDK.

for a middle

Can explain that util.Random is a 48-bit LCG that is predictable from a couple of outputs and that Math.random() shares it; lists concrete vulnerable values (tokens, salts, IVs).

for a senior

Articulates the CSPRNG unpredictability property (can't predict forward or backward), names the OS entropy seeding, and can audit a codebase for misuse.

for a principal

Sets org-wide guidance/linters (e.g. ban java.util.Random in security packages), reasons about entropy sources and FIPS requirements, and weighs SecureRandom usage in threat models.

## The problem: predictability A **random number generator** in software is almost always a **PRNG** (pseudo-random number generator): a deterministic algorithm that, starting from an initial value called a **seed**, produces a long sequence of numbers that *look* random. Because it is deterministic, the entire sequence is fully determined by the seed and the algorithm. `java.util.Random` uses a **linear congruential generator (LCG)**: each step computes `state = (state * a + c) mod 2^48` and returns bits of `state`. The key facts: - The seed/internal state is only **48 bits**. - The update rule is public and simple. This means an attacker who sees a small number of outputs can solve for the internal state and then **reproduce every future and past output**. There are well-known, fast techniques (and ready-made tools) to crack `java.util.Random` from just two consecutive `nextInt()` results. `Math.random()` is just a shared `java.util.Random` under the hood, so it has the exact same weakness. ## Why that matters for security Many security values must be **unguessable**: - **Session tokens / password-reset tokens** — guess one and you hijack an account. - **API keys, CSRF tokens, nonces** — predictability defeats their purpose. - **Cryptographic keys, IVs, salts** — predictable values break the encryption or hashing that relies on them. If any of these come from `java.util.Random`, an attacker who collects a few values can predict the rest. This is a real, exploited class of vulnerability, not a theoretical one. ## The fix: a CSPRNG A **CSPRNG** (cryptographically secure PRNG) is a PRNG designed so that, even seeing many past outputs, you **cannot predict the next output** better than guessing, and you cannot run it backwards to recover earlier outputs. In Java this is `java.security.SecureRandom`. Key differences from `java.util.Random`: - It is seeded from the **operating system's entropy source** (e.g. `/dev/urandom` on Linux, the OS CSPRNG on Windows), not a fixed or time-based value. - It has a much larger internal state and a cryptographic algorithm, so its output is not invertible to a small seed. - `SecureRandom extends java.util.Random`, so it has the same methods (`nextInt`, `nextBytes`, `nextLong`…), making it a drop-in replacement. ## Practical rule > If the value protects, authenticates, or hides something, generate it with `SecureRandom`. Use `java.util.Random`/`Math.random()` only for non-security purposes (games, simulations, load balancing, sampling). For filling a buffer (token/key/salt bytes) use `secureRandom.nextBytes(buf)`. Never wrap or seed it from `System.currentTimeMillis()` — that reintroduces predictability.

  • Roughly how many outputs does an attacker need to predict a java.util.Random sequence?
    Very few — typically just two consecutive outputs are enough to recover the 48-bit internal state and then reproduce all subsequent (and prior) values.
  • Is SecureRandom a subclass of java.util.Random?
    Yes. SecureRandom extends java.util.Random, so nextInt/nextLong/nextBytes etc. are available and it can replace Random directly in security code.

saying these in an interview costs you the question

  • Saying java.util.Random is fine if you 'seed it well' — the algorithm itself is the weakness
  • Believing Math.random() is more secure than new Random()
  • Thinking you need a third-party library — SecureRandom is built in
  • Confusing 'looks random to me' with cryptographically unpredictable

context

open as a page

What happens if you construct or seed SecureRandom with a fixed seed, and why is that dangerous?

level: middleimportance: must knowfreq 60%

basics

~20 s

A fixed seed makes the output deterministic — the same 'random' values every run — which is fine for tests but disastrous for real secrets, because anyone with the seed (or who guesses it) can reproduce every token or key.

open as a page

How do you use SecureRandom to fill a key, IV, salt, or token buffer, and what should you avoid when doing so?

level: middleimportance: must knowfreq 70%

basics

~10 s

Create one SecureRandom, make a byte[] of the size you need, and call secureRandom.nextBytes(buffer). That fills it with unpredictable bytes. Avoid building random bytes from Random, timestamps, or fixed seeds.

open as a page

What is the difference between new SecureRandom() (the default instance) and SecureRandom.getInstanceStrong(), and when would you use each?

level: seniorimportance: should knowfreq 55%

basics

~10 s

new SecureRandom() gives a strong, non-blocking generator good for almost everything. getInstanceStrong() returns a platform-configured 'strong' algorithm that may block waiting for entropy; reserve it for rare, very high-value secrets like long-lived keys.

open as a page

What are SecureRandom 'algorithms' like NativePRNG, SHA1PRNG, and DRBG, and how does platform/provider selection affect portability and reproducibility?

level: principalimportance: nice to knowfreq 35%

basics

~20 s

SecureRandom is provided by named algorithms (NativePRNG reads the OS source, SHA1PRNG is a self-contained generator, DRBG is the modern NIST design). Which you get depends on the platform/provider, so behavior can differ across OSes unless you request one explicitly.

open as a page