When generating random numbers in Java for cryptographic purposes, many developers often use the java.security.SecureRandom class. And while the java.security.SecureRandom class is designed to generate cryptographically secure random numbers, there are a few subtleties in the API, and if it is used improperly the output can become predictable. At Cigital we have witnessed a number of cases where this is true. The following is a guide to the proper use of Java’s java.security.SecureRandom class.
First, let’s take a quick look at how the java.security.SecureRandom API works. The java.security.SecureRandom class does not actually implement a pseudorandom number generator (PRNG) itself. It uses PRNG implementations in other classes to generate random numbers. A number of actual PRNGs may actually be used when an instance of java.security.SecureRandom is created. The PRNGs are part of Java cryptographic service providers (CSPs). In Sun’s Java implementation, the SUN CSP is used by default. On Windows, the SUN CSP uses the SHA1PRNG implemented in sun.security.provider.SecureRandom by default. On Solaris and Linux, the SUN CSP default is to use sun.security.provider.NativePRNG which simply provides the output of the /dev/urandom PRNG provided by the operating system. If however, on Solaris/Linux, the java.security configuration file in the JRE is modified such that securerandom.source is set to something other than file:/dev/urandom, then the SHA1PRNG implemented in sun.security.provider.SecureRandom is used, as on Windows. Of course, an application can choose not to use the defaults, and can always specify a particular PRNG implemented by a particular cryptographic provider. In Cigital’s experience, most Java applications that use java.security.SecureRandom actually use the SHA1PRNG provided by the SUN CSP under the cover.
Now, an application will end up with an instance of SHA1PRNG implemented in sun.security.provider.SecureRandom using the following calls:
Note that according to Sun’s documentation, the returned java.security.SecureRandom instance is not seeded by any of these calls. If after one of these calls, java.security.SecureRandom.nextBytes(byte) is called, then the PRNG is seeded using a secure mechanism provided by the underlying operating system (starting with JRE 1.4.1 in Windows and JRE 1.4.2 in Linux and Solaris). If java.security.SecureRandom.setSeed(long) or java.security.SecureRandom.setSeed(byte) is called before a call to java.security.SecureRandom.nextBytes(byte), then the internal seeding mechanism is bypassed, and only the provided seed is used to generate random numbers.
For those who are not familiar with the inner workings of cryptographic PRNGs, their job is to take a relatively small random seed and use it to produce deterministic output that seems random to anybody that does not know what the seed is. The PRNG tries to ensure that the output does not reveal any information about the seed, and that somebody observing the output cannot predict future outputs without knowing the seed.
By bypassing the internal secure seeding mechanism of the SHA1PRNG, you may compromise the security of your PRNG output. If you seed it with anything that an attacker can potentially predict (e.g. the time when the PRNG instance was created), then using java.security.SecureRandom may not provide the level of security that you need.
Finally, regardless of how well the PRNG is seeded, it should not be used indefinitely without reseeding. There are two approaches that can be used for longer-term security of PRNG output:
In summary, keep the following in mind when using java.security.SecureRandom:
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "SUN");
See other posts on SecureRandom
Issues to be aware of when using Java’s SecureRandom
SecureRandom Implementation (sun.security.provider.SecureRandom – SHA1PRNG)
SecureRandom Implementation (sun.security.provider.NativePRNG)
Amit Sethi, Principal Consultant, has been with Cigital since 2004. He specializes in Mobile Security, Online Game Security and Cryptography. Amit’s work includes extracting cryptographic keys from embedded devices using side-channel attacks, designing mechanisms to make those attacks more difficult, and designing a format-preserving encryption algorithm based on well-studied cryptographic primitives for a Fortune 500 company. Even in his free time, Amit enjoys reverse engineering binaries, analyzing open source software, and experimenting with new technologies.
Words of Security Wisdom: Just because you don’t know of any security incidents in your software/environment doesn’t mean that you haven’t had any security incidents –especially if you don’t have good monitoring controls in place.
Cigital is one of the world’s largest application security firms. We go beyond traditional testing services to help our clients find, fix and prevent vulnerabilities in the applications that power their business.
Our experts also provide remediation guidance, program design services, and training that empower you to build and maintain secure applications.
Software Developers vs. Software Security: Why Can’t We All Get Along?
Gary McGraw discusses the security risks of dynamic code
The Cathedral and the Bazaar of Software Security Vulnerabilities
Serving Resources Over SSL With CSP Upgrade-Insecure-Requests
RT @cigitaljobs: .@cigitaljobs will soon combine with @cigital! Follow @Cigital to stay current on our #appsec opportunities! pic.twitter.com/au4vYsJnnW
Yesterday at 3:30 pm
RT @RSAConference: The top 10 online #safety tips. Share these with your family! #RSACCyberSafety: spr.ly/6016By8Jo
Yesterday at 12:04 pm
"What’s the cause of the developer/security divide?" @cketkar | sws.ec/1Xg2uI9
RT @CIOonline: Study: 81% of large healthcare organizations breached trib.al/0LNe6I8 @CIOonline #healthcare #breaches
Yesterday at 12:02 pm
Researchers discover new keychain vulnerability in OSX via @CSOonline | sws.ec/1EyGeTM pic.twitter.com/5XMomoes8b
Yesterday at 11:07 am