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    }