What happens if you construct or seed SecureRandom with a fixed seed, and why is that dangerous?
answer
- Fixed seed -> deterministic, repeatable output
- Unpredictability comes only from OS entropy seeding
- SHA1PRNG + setSeed-before-use = fully determinized
- Default NativePRNG setSeed only ADDS entropy, doesn't replace
- Seeded RNG OK for tests, never in production
basics
~20 sA 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.
solid answer
~50 sSecureRandom is still a deterministic algorithm; its unpredictability comes from being seeded with high-entropy OS data. If you supply a fixed seed — via new SecureRandom(seedBytes) on some algorithms, or by calling setSeed(constant) on a freshly created SHA1PRNG-style instance before any other use — you can pin the output so it repeats identically every run. That is sometimes done deliberately for reproducible tests, but in production it is a severe vulnerability: an attacker who knows or guesses the seed can regenerate every salt, IV, key, and token you produce. Two important nuances: setSeed semantics differ by algorithm — on the default native PRNG, setSeed only mixes additional entropy in rather than replacing it, so it won't fully determinize output — but SHA1PRNG seeded immediately after construction will. Never hardcode seeds in security code, and never derive a seed from a timestamp or other low-entropy value.
code
java · 21 linesimport java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
class SeedDanger {
// DANGEROUS: SHA1PRNG seeded immediately -> identical output every run.
static byte[] reproducibleAndBroken() throws NoSuchAlgorithmException {
SecureRandom r = SecureRandom.getInstance("SHA1PRNG");
r.setSeed("hardcoded-seed".getBytes()); // pins the sequence
byte[] token = new byte[16];
r.nextBytes(token); // same bytes on every JVM run
return token;
}
// SAFE: let SecureRandom self-seed from OS entropy; never set a fixed seed.
static byte[] safe() {
SecureRandom r = new SecureRandom();
byte[] token = new byte[16];
r.nextBytes(token); // unpredictable
return token;
}
}go deeper
Understands that a fixed seed means the same values every run and that this must not be used for real secrets.
Explains that unpredictability comes from OS entropy, that hardcoded/time-based seeds are dangerous, and that seeded RNGs are only for tests.
Knows the algorithm-dependent setSeed semantics (SHA1PRNG replaces vs default supplements) and the concrete consequences like IV reuse breaking GCM/CTR.
Sets policy banning fixed/low-entropy seeds, designs test seams that inject randomness without polluting production, and reviews for IV/salt reuse risks.
## Why a seed matters Every PRNG, including the cryptographically secure `SecureRandom`, is a **deterministic** algorithm: same starting state in, same sequence out. The only thing that makes `SecureRandom`'s output unpredictable is that it is **seeded from high-entropy operating-system randomness** that an attacker cannot observe. Remove or fix that seed and the 'randomness' becomes reproducible. ## How a fixed seed gets introduced There are two main ways developers accidentally (or intentionally) pin the output: 1. **Constructor with a seed:** `new SecureRandom(byte[] seed)`. On some algorithms this initializes the generator from exactly those bytes, so a constant seed → constant output. 2. **setSeed before first use:** Calling `secureRandom.setSeed(fixedBytes)` on a **freshly created** instance of an algorithm like **SHA1PRNG** uses that seed as the entire starting state, producing a fixed sequence. If the seed is a literal in code (e.g. `setSeed("12345".getBytes())`) or derived from something low-entropy (e.g. `setSeed(System.currentTimeMillis())`), the output is predictable. ## Why it's dangerous With a known/fixed seed, **every** secret you generate is reproducible by anyone who has (or guesses) the seed: - Salts repeat → password hashes become attackable / non-unique. - IVs repeat → encryption leaks patterns (catastrophic for modes like CTR/GCM where IV reuse breaks the cipher). - Tokens/keys repeat → forgery, account takeover, key compromise. A hardcoded seed is essentially shipping your secrets' recipe in source control. ## A crucial algorithm nuance: setSeed behavior differs `setSeed` does **not** mean the same thing for every algorithm: - For **SHA1PRNG**, calling `setSeed` right after construction (before any output) makes the seed the complete initial state → fully deterministic. - For the **default NativePRNG / DRBG**, `setSeed` typically **supplements** the existing OS-seeded state with additional entropy rather than replacing it. So `setSeed(constant)` there mixes in (harmless) extra bytes and does **not** make output reproducible. This is why a 'set a fixed seed to determinize SecureRandom' trick works on SHA1PRNG but may silently *not* work on the default — leading to confusing behavior. The safe rule ignores these subtleties: **never fix the seed in production**. ## Legitimate use: reproducible tests In unit tests you sometimes *want* deterministic 'random' values so assertions are stable. There it's acceptable to use a seeded SHA1PRNG (or better, inject a fake/stubbed source). Keep that strictly out of production code paths. ## Rules - Don't pass a fixed seed to the constructor or `setSeed` in production. - Don't seed from time, PID, counters, or any guessable value. - Let `SecureRandom` self-seed from the OS; you generally never need to call `setSeed` at all. - If you need determinism for tests, isolate it and make it obvious it's test-only.
- Does setSeed always make SecureRandom deterministic?No. With SHA1PRNG called immediately after construction it does. With the default NativePRNG/DRBG, setSeed usually only mixes extra entropy into the already OS-seeded state, so output stays unpredictable.
- When is a fixed seed acceptable?Only in tests that need reproducible 'random' values, kept strictly out of production code — and even then, injecting a fake randomness source is cleaner.
saying these in an interview costs you the question
- Hardcoding a seed in production for 'consistency'
- Seeding from System.currentTimeMillis()/nanoTime() (low entropy, guessable)
- Assuming setSeed always determinizes output (algorithm-dependent)
- Reusing IVs because a fixed seed reproduces them — breaks ciphers like GCM/CTR