001 package org.rakeshv.utils;
002
003 import java.security.SecureRandom;
004
005 /**
006 * A utility class that can be used to generate secure random password
007 * values.
008 *
009 * <p>Copyright 2005-2006 Rakesh Vidyadharan</p>
010 * @author Rakesh Vidyadharan 2005 August 25
011 * @version $Id: PasswordGenerator.java,v 1.3 2006/03/11 04:15:14 rakesh Exp $
012 * @since 1.17
013 */
014 public final class PasswordGenerator extends Object
015 {
016 /**
017 * The default characters that are allowed in a password value.
018 */
019 private static final char[] PASSWORD_CHARACTERS =
020 ( "abcdefghijklmnopqrstuvqxyz" +
021 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
022 "`1234567890~!@#$%^&*()" ).toCharArray();
023
024 /**
025 * The random number generator.
026 */
027 private static final SecureRandom random = new SecureRandom();
028
029 /**
030 * Default constructor. Cannot be instantiated.
031 */
032 private PasswordGenerator()
033 {
034 super();
035 }
036
037 /**
038 * Generate a random password of the specified length.
039 *
040 * @see #generatePassword( int, char[] )
041 * @param length The desired length of the password.
042 * @return char[] The array of characters that comprise the random
043 * password.
044 */
045 public static final char[] generatePassword( int length )
046 {
047 return generatePassword( length, PASSWORD_CHARACTERS );
048 }
049
050 /**
051 * Generate a random password of the specified length and restricted
052 * to the characters specified.
053 *
054 * @param length The desired length of the password.
055 * @param characters The array of valid characters thay may be used
056 * in the password.
057 * @return char[] The array of characters that comprise the random
058 * password.
059 */
060 public static final char[] generatePassword( int length,
061 char[] characters )
062 {
063 char[] password = new char[length];
064
065 try
066 {
067 random.setSeed( System.currentTimeMillis() );
068
069 byte[] intbytes = new byte[4];
070
071 for ( int i = 0; i < length; ++i )
072 {
073 random.nextBytes( intbytes );
074 password[i] = characters[
075 Math.abs( getIntFromByte( intbytes ) % characters.length ) ];
076 }
077 }
078 catch (Exception ex)
079 {
080 System.err.println( "Unable to generate random password.\n" +
081 StringUtilities.stackTrace( ex ) );
082 }
083 return password;
084 }
085
086 /**
087 * Convert a byte value returned by the random number generator
088 * ({@link #random}) to an integer that may be used to index into
089 * the allowable characters array.
090 *
091 * @param bytes The byte values returned by the random number
092 * generator.
093 */
094 private static final int getIntFromByte( byte[] bytes )
095 {
096 int returnNumber = 0;
097 int index = 0;
098 returnNumber += byteToInt( bytes[index++] ) << 24;
099 returnNumber += byteToInt( bytes[index++] ) << 16;
100 returnNumber += byteToInt( bytes[index++] ) << 8;
101 returnNumber += byteToInt( bytes[index++] ) << 0;
102 return returnNumber;
103 }
104
105 /**
106 * Convert a byte value into a postive integer.
107 *
108 * @param byteValue The byte that is to be converted into an integer.
109 * @return int The converted positive value.
110 */
111 private static final int byteToInt( byte byteValue )
112 {
113 return (int) byteValue & 0xFF;
114 }
115 }