Monday, October 20, 2008

using secure random and message direct to generate random nad unique number

The following method uses SecureRandom and MessageDigest :

  • upon startup, initialize SecureRandom (this may be a lengthy operation)
  • when a new identifier is needed, generate a random number using SecureRandom
  • create a MessageDigest of the random number
  • encode the byte[] returned by the MessageDigest into some acceptable textual form
  • check if the result is already being used ; if it is not already taken, it is suitable as a unique identifier
The MessageDigest class is suitable for generating a "one-way hash" of arbitrary data. (Note that hash values never uniquely identify their source data, since different source data can produce the same hash value. The value of hashCode, for example, does not uniquely identify its associated object.) A MessageDigest takes any input, and produces a String which :
  • is of fixed length
  • does not allow the original input to be easily recovered (in fact, this is very hard)
  • does not uniquely identify the input ; however, similar input will produce dissimilar message digests
MessageDigest is often used as a checksum, for verifying that data has not been altered since its creation.

Example

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

public class GenerateId {

public static void main (String... arguments) {
try {
//Initialize SecureRandom
//This is a lengthy operation, to be done only upon
//initialization of the application
SecureRandom prng = SecureRandom.getInstance("SHA1PRNG");

//generate a random number
String randomNum = new Integer( prng.nextInt() ).toString();

//get its digest
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte[] result = sha.digest( randomNum.getBytes() );

System.out.println("Random number: " + randomNum);
System.out.println("Message digest: " + hexEncode(result) );
}
catch ( NoSuchAlgorithmException ex ) {
System.err.println(ex);
}
}

/**
* The byte[] returned by MessageDigest does not have a nice
* textual representation, so some form of encoding is usually performed.
*
* This implementation follows the example of David Flanagan's book
* "Java In A Nutshell", and converts a byte array into a String
* of hex characters.
*
* Another popular alternative is to use a "Base64" encoding.
*/

static private String hexEncode( byte[] aInput){
StringBuilder result = new StringBuilder();
char[] digits = {'0', '1', '2', '3', '4','5','6','7','8','9','a','b','c','d','e','f'};
for ( int idx = 0; idx < aInput.length; ++idx) {
byte b = aInput[idx];
result.append( digits[ (b&0xf0) >> 4 ] );
result.append( digits[ b&0x0f] );
}
return result.toString();
}
}


Example run :

>java -cp . GenerateId
Random number: -1103747470
Message digest: c8fff94ba996411079d7114e698b53bac8f7b037

No comments: