How to properly use setSeed() method in SecureRand

2019-08-29 11:51发布

问题:

I want to produce the two prime numbers for RSA key generation. I think in order to increase both primes' randomness, the random may be generated as the following:

SecureRandom r = SecureRandom.getInstance("SHA1PRNG");
r.setSeed(1232);
p = BigInteger.probablePrime(1024, r);
q = BigInteger.probablePrime(1024, r);

My question is: Do you think using SecureRandom will increase the p and q randomness? If so, how can I randomly set the value of setSeed() instead of making it a fixed value ( here i chose 1232)?

回答1:

As CodesInChaos already shows, the default implementation of the SUN provider automatically seeds itself using the system random number generator. As Java itself doesn't have an (explicit) entropy source it is more or less dependent on the system for its seed.

You should never call setSeed before retrieving data from the "SHA1PRNG" in the SUN provider as that will make your RNG (Random Number Generator) into a Deterministic RNG - it will only use the given seed instead of adding the seed to the state. In other words, it will always generate the same stream of pseudo random bits or values.

The initial call to setSeed may differ per provider. Sometimes it will use the seed as only seed, but it may also just add the seed to the current state. On later Android versions (4.2 onwards) the seed is just added to the random state, so the "SHA1RNG" will stay fully random.

Probably the best way to generate your random number generator is just

SecureRandom r = new SecureRandom();

and let the Java runtime figure out the best one.

if you want to use an explicit algorithm (which is, however, ill-described by SUN/Oracle) then you could use:

SecureRandom r = SecureRandom.getInstance("SHA1PRNG");

as in your code. If you want to add entropy, use:

// just used to make sure that the SecureRandom is seeded by the OS
r.nextBytes(new byte[8]);
r.setSeed(1232);

A constant value or literal doesn't contain much (if any) entropy. Usual sources of entropy are the current time (or even better, System.nanoTime()), mouse movements etc.


For Java 8 there is a new method getInstanceStrong() with the following description:

Returns a SecureRandom object that was selected by using the algorithms/providers specified in the securerandom.strongAlgorithms Security property.

Some situations require strong random values, such as when creating high-value/long-lived secrets like RSA public/private keys. To help guide applications in selecting a suitable strong SecureRandom implementation, Java distributions include a list of known strong SecureRandom implementations in the securerandom.strongAlgorithms Security property.

Which should be used as a replacement for the call to the constructor. Be warned that this may return a blocking RNG, that is: an RNG that may block your thread until sufficient entropy has become available. It may also drain your OS entropy pool blocking other applications, so only use it sparingly.