HOWTO: Using Java's SecureRandom (java.security.SecureRandom)

| No TrackBacks
If you're ever in a situation where you need to generate a cryptographically strong random number, then you might be interested in learning a little more about Java's java.security.SecureRandom. So, what's the difference between java.util.Random and java.security.SecureRandom?  Well, SecureRandom is special because it aims to make it more difficult to programatically predict the next random number in a sequence.  And, not surprisingly, guessing or predicting random numbers in an insecure random sequence is trivial.  So, any crypto-based code that requires a random number for digital signature generation, session key generation, etc., should always use SecureRandom.

1 - Troublesome Scenario

Here's a simple scenario that illustrates why Random isn't ideal for secure applications: imagine if an application generated a session key using Random (predictable).  If a hacker got their hands on a few sequential session keys from that insecure Random generator, with little work, they can predict the next session key in the sequence.  This could then be used for a number of attacks, including hijacking a user session.


2 - My SecureRandomNumber Class (an example)

Here's my SecureRandomNumber class.  It's available for use in your projects under the MIT License.  This class also shows how to use Java's SecureRandom, if you don't want to directly use this code:

/**
* Copyright (c) 2009 Mark S. Kolich
* http://mark.koli.ch
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/

import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class SecureRandomNumber {

private static final String SHA1_PRNG = "SHA1PRNG";

// Default here is 64-bits of random goodness.
private static final int DEFAULT_RANDOM_SIZE = 64;

private static final char HEX_DIGIT [] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};

// This isn't thread safe but we probably don't really care
// since all we're doing is reading a bunch of random numbers
// out of the generator.
private static final SecureRandom sRandom__;
static {
try {
sRandom__ = SecureRandom.getInstance( SHA1_PRNG );
} catch ( NoSuchAlgorithmException e ) {
throw new Error(e);
}
}

/**
* Get the number of next random bits in this SecureRandom
* generators' sequence.
* @param size how many random bits you want
* @return
* @throws IllegalArgumentException if the arg isn't divisible by eight
*/
public static byte [] getNextSecureRandom ( int bits ) {

// Make sure the number of bits we're asking for is at least
// divisible by 8.
if ( (bits % 8) != 0 ) {
throw new IllegalArgumentException("Size is not divisible " +
"by 8!");
}

// Usually 64-bits of randomness, 8 bytes
final byte [] bytes = new byte[ bits / 8 ];

// Get the next 64 random bits. Forces SecureRandom
// to seed itself before returning the bytes.
sRandom__.nextBytes(bytes);

return bytes;

}

/**
* Convert a byte array into its hex String
* equivalent.
* @param bytes
* @return
*/
public static String toHex ( byte [] bytes ) {

if ( bytes == null ) {
return null;
}

StringBuilder buffer = new StringBuilder(bytes.length*2);
for ( byte thisByte : bytes ) {
buffer.append(byteToHex(thisByte));
}

return buffer.toString();

}

/**
* Convert a single byte into its hex String
* equivalent.
* @param b
* @return
*/
private static String byteToHex ( byte b ) {
char [] array = { HEX_DIGIT[(b >> 4) & 0x0f],
HEX_DIGIT[b & 0x0f] };
return new String(array);
}

/**
* An example showing how to use SecureRandomNumber.
* @param args
*/
public static void main ( String [] args ) {

for ( int i = 0; i < 10; i++ ) {

// Get 64-bits of secure random goodness.
final byte [] randBytes =
SecureRandomNumber.
getNextSecureRandom(
DEFAULT_RANDOM_SIZE );

// Convert it to something pretty.
System.out.println(
SecureRandomNumber.toHex( randBytes ) );

}

}

}

Download SecureRandomNumber.java here.

Cheers.

Did You Find this Helpful?

Did you find this post helpful, or at least, interesting?

  

Send Mark a Direct Message

If you'd like to send me a direct message, please do so below. However, I do not publicly post comments or messages submitted directly to me. So, if you're going to try to SPAM me, or my blog, you're pretty much wasting your time.

400 characters remaining

Error

About Mark

A Silicon Valley native, Mark Kolich is a full-time Software Engineer, a casual entrepreneur, and a consultant for hire. A web technologies expert, his current focus is on building powerful and robust cloud-driven web-applications using Java, PHP, Perl, AJAX, DHTML, CSS, and JavaScript. His favorite programming languages are PHP, Java and JavaScript. He uses Linux, enjoys biking to work, loves building great software, and always writes elegant, readable, and maintainable code.

No TrackBacks

No trackbacks attached to this entry.

Twitter (@markkolich)

Translate

About this Entry

This page contains a single entry by Mark Kolich published on May 29, 2009 1:12 PM.

A Couple of Quick jQuery Tips: Alternating Gray Rows in a Table, Highlight Table Row Mouseover was the previous entry in this blog.

PHP Comparison Operators Quick Reference Card is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.