Random vs. SecureRandom

Java Random Number Generation java.util.Random vs java.security.SecureRandom

Recently, I found myself working on a project that requires me to create signing keys and other secret values.  I’ve been aware of the fact that java.util.Random doesn’t generate truly random numbers and also knew of the existence of the java.security.SecureRandom class.  I started reading about SecureRandom and became interested in the details.

Random

  • Seed length is 48 bits
  • Sets the seed from the System clock
  • Uses a linear congruential pseudorandom number generator
  • Easy to predict
  • Use for random numbers that aren’t important to security

SecureRandom

  • Sets the seed using a Security Provider and Algorithm.  Varies depending on the operating system and how security is configured
    • On Windows (without extra security configuration), it defaults to the Sun provider and uses SHA1PRNG
    • On Unix/Linux etc, it uses a NativePRNG that seeds from the dev/urandom or dev/random (for Strong instances).
  • Produces non-deterministic output
  • Must comply with:
  • Use anytime you’re generating numbers for security or cryptographic purposes

Usage

SecureRandom extends Random and usage of each of them is nearly identical.  Both allow setting your own seed and SecureRandom has additional features for providing a Provider and Algorithm.  Based on my research, the common recommendation for most applications is to instantiate a default SecureRandom and let it choose the provider and self-seed.  In each case, the class is instantiated and then gets ten integers between 0 and 1000.  Additionally at the very end, I demonstrate how to print out which Provider and Algorithm my SecureRandom instance is using.

 //Random auto-seed
 System.out.println("Random with auto-generated seed");
 Random random = new Random();
 for(int i = 0; i < 10; i++) {
    int rnd = random.nextInt(1000);
    System.out.println(i + " " + rnd);
 }
 
 System.out.println();
 
 //SecureRandom auto-seed
 System.out.println("SecureRandom with auto-generated seed");
 SecureRandom secureRandom = new SecureRandom();
 for(int i = 0; i < 10; i++) {
    int rnd = secureRandom.nextInt(1000);
    System.out.println(i + " " + rnd);
 }
 
 System.out.println("Using provider: " + secureRandom.getProvider() + " and algorithm " + secureRandom.getAlgorithm());

Output

As with the usage, the output also looks very similar.  At the end you can see that my SecureRandom used the Sun Provider with SHA1PRNG (I’m on Windows).

Random with auto-generated seed
0 927
1 557
2 252
3 351
4 962
5 230
6 468
7 698
8 431
9 304

SecureRandom with auto-generated seed
0 918
1 197
2 191
3 779
4 781
5 711
6 835
7 636
8 293
9 687
Using provider: SUN version 1.8 and algorithm SHA1PRNG

SecureRandom Strong Instance

SecureRandom also provides a method for getting an instance that produces strong random values.  One might use a strong instance for high value/long term secrets. The strong instance will use the provider’s strongAlgorithm.  On a *nix system, this typically means the seed is generated using dev/random instead of dev/urandom.  Something to note is that dev/random will block if it doesn’t have enough entropy gathered up for the seed being requested.

Conclusion

I’ve shown the basic usage of each class and tried to discuss some of the differences.  I found it especially interesting to read about how *nix systems collect entropy.  Some open questions for me are how do Windows systems collect entropy?  Are secrets generated on a Window system somehow less secure?

References

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s