Why is java.util.Random considered predictable and unsuitable for security purposes?
answer
- LCG, 48-bit state, public constants
- invertible: outputs reveal the state
- ~2 outputs -> recover state -> predict all
- default seed = time/counter, also guessable
- fix = SecureRandom (CSPRNG), not 'encryption'
basics
~20 sIt uses a simple math formula with a small, public starting state. If someone sees a few of its numbers, they can figure out the formula's state and predict every number it will produce next.
solid answer
~40 sjava.util.Random is a linear congruential generator (LCG) with only 48 bits of internal state, advanced by a fixed, publicly documented formula. Because the algorithm and its constants are known, an attacker who observes a small number of outputs can solve for the current 48-bit state and then reproduce the entire forward and backward sequence — there's no secret beyond that tiny state. The default seed is derived from system time/an atomically incremented counter, which is also guessable. For security you need a CSPRNG like SecureRandom, which pulls from OS entropy and uses algorithms specifically designed so that observing outputs gives no usable advantage in predicting the next one. So the issue isn't 'lack of encryption' — it's the small, recoverable state and deterministic, public algorithm.
go deeper
Knows you shouldn't use Random for passwords/tokens, even if hazy on why.
Can say Random is predictable and seedable and that SecureRandom is the secure alternative.
Explains the LCG mechanism, the 48-bit recoverable state, that public constants + a couple of outputs reveal the state, and that the default seed is guessable.
Frames it as PRNG vs CSPRNG (next-bit unpredictability), discusses real attack scenarios and remediation/lint policy, and corrects the 'not encrypted' misconception.
### Background: PRNG vs CSPRNG A **PRNG (pseudo-random number generator)** turns a starting **seed** into a stream of numbers via a fixed formula. A **CSPRNG (cryptographically secure PRNG)** adds a guarantee: even an adversary who sees many outputs cannot predict the next one (or recover previous ones) with any practical advantage. `java.util.Random` is a PRNG; it makes **no** such guarantee. ### How java.util.Random works It is a **linear congruential generator (LCG)**. It keeps a single 48-bit number, the *state*, and each step computes: ``` state = (state * 0x5DEECE66D + 0xB) & ((1 << 48) - 1) ``` The multiplier `0x5DEECE66D` and increment `0xB` are **constants published in the JDK source and the Javadoc**. Each call to `nextInt`/`nextLong` etc. advances the state and returns some of its high bits. ### Why that is predictable Three facts combine: 1. **The algorithm and constants are public.** There is no secret algorithm — only the 48-bit state is 'hidden'. 2. **The state is tiny (48 bits) and fully determines all output.** Knowing the state lets you compute every future *and* past value (the LCG is invertible). 3. **Outputs leak the state.** Each output reveals a chunk of the state bits. Observing just two or so consecutive 32-bit outputs is enough to brute-force/solve the remaining unknown bits and recover the full 48-bit state. After that, the attacker has the generator. On top of that, the **default seed** isn't secret either: it's built from the current time and a counter, so even *without* seeing outputs an attacker can narrow the seed space. ### Concrete attack picture Suppose you mint 'random' session tokens with `Random`. An attacker requests a couple of tokens, recovers the 48-bit state, then predicts the next token your server will hand out to a different user — full account takeover, no cryptography broken, just arithmetic. ### Why SecureRandom fixes it `SecureRandom` is a CSPRNG backed by the **JCA** and OS entropy sources (`/dev/urandom`, OS crypto APIs). It uses a large internal state seeded from real-world entropy and algorithms designed so outputs don't reveal the state. You cannot 'see two outputs and predict the third'. ### Common misframing to avoid People sometimes say Random is insecure because it 'isn't encrypted'. Encryption is unrelated. The real reasons are the **small, recoverable state** and the **deterministic, public algorithm**. Fixing it means switching the *generator*, not adding encryption.
- Does giving Random a long, secret seed make it secure?No. The state is still only 48 bits and the algorithm is public; outputs leak the state regardless of how you seeded it, so it remains predictable.
- What property does a CSPRNG add that an LCG lacks?Next-bit unpredictability: observing past outputs gives no practical advantage in predicting future outputs, because the state is large and outputs don't reveal it.
saying these in an interview costs you the question
- Saying it's insecure because output 'isn't encrypted'
- Believing a custom seed makes Random secure
- Thinking you'd need millions of samples to break it (a handful suffices)
- Confusing statistical quality with cryptographic unpredictability