7

I'd like to consult some question on the common myth of SecureRandom in Java, on security vs. performance tradeoff.

I've been researching on the Internet for a while and I've put the following information together. I'd like people here help me confirm what I got and hopefully get some ideas on what to actually choose for implementation.

Basically here are some most popular and thorough articles for SecureRandom:

Proper use of Java's SecureRandom: https://www.synopsys.com/blogs/software-security/proper-use-of-javas-securerandom/

Issues when using Java's SecureRandom: https://www.synopsys.com/blogs/software-security/issues-when-using-java-securerandom/

Using the SecureRandom class: http://moi.vonos.net/java/securerandom/

And, Sun's official "confession" of bug/confusion and a proposed release in Java 8: http://openjdk.java.net/jeps/123

Now that Java 8 is out, I am honestly not sure how better this actually been fixed, by just looking at the documentation: http://docs.oracle.com/javase/8/docs/api/java/security/SecureRandom.html

So after all, this is what I got (please help me to see if I got them sorted):

People like Amit Sethi suggests using specified instantiation like: SecureRandom sr3 = SecureRandom.getInstance("SHA1PRNG", "SUN"), where in reality, Sun tells us that this will end up always reading from /dev/random(???), which means it can be potentially blocking for EVERY call. As opposed to if you use new SecureRandom() it will then always read from /dev/urandom unless generateSeed() is called. See

http://bugs.java.com/view_bug.do?bug_id=6202721

Does that mean "new SecureRandom()" is still preferred in current Java? Not many other documenation I found state the above point explicitly so I want to know if that is still true?

Now if "new SecureRandom()" is the choice and will lead to never blocking call, then I think what I should do for periodic reseeding would be:

Make SecureRandom a static instance in the class and let another Executor thread periodically call generateSeed() on it, thus even though the call is blocking, it's not affecting my main request handling thread in my application. Does that sound like a good way doing it?

Really appreciate any Java and crypto experts to shed some light on this issue here. Thanks!

Edit: Another useful thread here, seems to back up my guess: https://bugs.openjdk.java.net/browse/JDK-4705093

Superziyi
  • 609
  • 1
  • 9
  • 30

2 Answers2

4

EDIT : First of all; if /dev/random or /dev/urandom blocks it makes sense to first try and fix that particular issue. The solutions below are about trying to fix the SecureRandom in Java itself, so it is less dependent on those special devices.


Make SecureRandom a static instance in the class and let another Executor thread periodically call generateSeed() on it, thus even though the call is blocking, it's not affecting my main request handling thread in my application. Does that sound like a good way doing it?

No, you should in that case use nextBytes() as the internal call generateSeed() uses the original supplier of seed information. In other words, you could as well create a separate instance of SecureRandom. Note that whenever you have a SecureRandom instance with a high enough state and a good backing algorithm it is not needed to reseed often (as it is very unlikely to create a cycle). If you ever require higher entropy, generate a new random class each time or use a random retrieved using SecureRandom.getInstanceStrong().

Using the default new SecureRandom() is probably best. Normally you should always supply the precise algorithm name for cryptographic algorithms (e.g. "AES/CBC/PKCS5Padding") but for secure random functionality it is better to let the system figure out which algorithm is best. If you want to change anything, change it through the command line constructs and make sure that /dev/urandom is available on Unix systems.

If you still have issues with blocking, then create a central, system seeded SecureRandom. Create new seed material using nextBytes() and supply this to a new SecureRandom using the SecureRandom(byte[] seed) constructor. This method should only be used if new SecureRandom() fails to handle the situation.

Even though supplying the initial seed is now explicit by using a constructor, the constructor itself does not guarantee that it is solely used for seeding the RNG. It's however likely that it is the case, so it is less likely to block. SecureRandom is thread safe so you don't need to synchronize access to it.

Using the new Java 8 SecureRandom.getInstanceStrong() is more likely to block. I presume that they have added that to make the default instances non-blocking. RSA key pair generation usually wants a lot of entropy, so it is likely that instances returned do use blocking calls to /dev/random.

All in all, using SecureRandom for special cases is still rather mucky. Fortunately this is only an issue for a very limited amount of use cases.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • Thanks for the information here. Sorry but mind me clarifing a bit...I need high security --- so do need periodic reseeding (unless it's just unnecessary worry?), while non-blocking for any call. What's the downside of using a timertask type stuff to do the reseeding job? Creating "new instance" like "new SecureRandom()", in my understanding, will never reseed, even though it's a "new instance". But then using getInstance call with specified algorithm, or using "getInstanceStrong()" as you mentioned, are likely to block, which is not desired...What exactly is the best approach here? – Superziyi Apr 14 '14 at 17:43
  • 1
    Getting it right is a balancing act. You've got one important advantage though; once a PRNG is well seeded you can request a lot of data from it before it cycles (gets to a previous state, so it will repeat the random bytes). Normally that is around half of the size of the inner state. For SHA-1 that is still 2^80 rounds, a horribly large number. So in principle you don't *have to* reseed. You could however reseed if you are afraid that the inner state gets compromised, e.g. because of side channel information. Random number quality is and always will be a tricky subject though. – Maarten Bodewes Apr 14 '14 at 19:02
  • Thanks. I guess there aren't really "absolute correct way" here, as you said, it's all about balancing and tradeoff. It could be, I am just underestimating the security SecureRandom provides without reseeding, as people normally do :-) I will just go with one design and let my colleague help review. Anyway good information and food for thought here for people searching the same thing around and I will mark your answer as accepted. – Superziyi Apr 15 '14 at 18:35
0

You can reduce the blocking using haveged to generate entropy. This is particularly useful in cloud managed servers where entropy sources are a lot less.

Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265