For benchmarking purposes, I'd like to have a SecureRandom produce deterministic output. Is this possible through the use of a seed (or maybe specification of an algorithm)?
import java.security.SecureRandom;
class TestSecureRandom {
public static void main(String [] args) {
SecureRandom rnd = new SecureRandom();
rnd.setSeed(1);
System.out.println(rnd.nextInt());
}
}
For me, the above program produces different values even though the seed is specified.
Many SecureRandom implementations are in the form of a pseudo-random number generator (PRNG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a true random seed. Other implementations may produce true random numbers, and yet others may use a combination of both techniques.
Thread safety. SecureRandom objects are safe for use by multiple concurrent threads. Implementation Requirements: A SecureRandom service provider can advertise that it is thread-safe by setting the service provider attribute "ThreadSafe" to "true" when registering the provider.
SecureRandom uses /dev/random as its entropy source and thus blocks when the kernel entropy pool runs out of entropy.
Size: A Random class has only 48 bits whereas SecureRandom can have up to 128 bits. So the chances of repeating in SecureRandom are smaller. Seed Generation: Random uses the system clock as the seed/or to generate the seed. So they can be reproduced easily if the attacker knows the time at which the seed was generated.
In order to override the default seed ,pass PRNG algorithm name like this
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
class TestSecureRandom {
public static void main(String [] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
rnd.setSeed("foo".getBytes("us-ascii"));
System.out.println(rnd.nextInt());
System.out.println(rnd.nextInt());
}
}
Ouput
-207444710
-1693504542
Everything is clearly explained in documentation:
Many SecureRandom implementations are in the form of a pseudo-random number generator (PRNG), which means they use a deterministic algorithm to produce a pseudo-random sequence from a true random seed. Other implementations may produce true random numbers, and yet others may use a combination of both techniques.
If you ask about implementation, in Linux it uses /dev/urandom
so the result is unpredictable. However, you can force SecureRandom
to use another algorithm:
SecureRandom rnd = SecureRandom.getInstance("SHA1PRNG");
But for many cases, most reasonable idea is to use some OOP patterns (e.g., jon-skeet's answer).
The simplest way of doing this is probably to make most of your code only depend on Random
, with an instance being injected (e.g. by passing it into a constructor). That way, for testing purposes you can pass in a simple Random
with a fixed seed - but for real runs where security is required, you can pass in an instance of SecureRandom
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With