Generating Passwords
Aye,
I want to generate passwords automatically. In the user-add-script I wrote, the one who is adding the new users is not to pick the passwords due to several irrelevant reasons.
My script already works, using the timestamp as password, but 14849248294829 isn't really a user-friendly password. I'd rather have a randomly generated password existing out of 6 or 8 letters. I do have a plan in pseudo code, but I just can't figure out how to convert it into actually working JSP.
Here's what I want to do:
[pseudo]
String[] letters = a,b,c (...)
for (i=0, i<9, i++){
*Randomly pick letters from the array.*
}
String pass = above blabla.
[/pseudo]
I guess that's a fair way of generating the passwords, but I haven't figured out how to actually program it properly.
Does someone have any idea?
[883 byte] By [
Nidhuggura] at [2007-11-27 7:55:23]

# 1
How about this way; using Random?
static final int SMALL_LETTERS_BASE_VALUE = 97;
static final int CAPITAL_LETTERS_BASE_VALUE = 65;
String password = "";
int currentValue = 0;
Random randomGenerator = new Random();
for ( int i = 0; i < 8; i++ )
{
switch ( (int) (Math.random()*10))
{
//Cases to generate small case letters
case 0:
case 1:
case 2:
case 3:
currentValue = randomGenerator.nextInt(26); //get an int from 0-25 for a letter
currentValue += SMALL_LETTERS_BASE_VALUE; //add the ASCII value for 'a' to get ASCII values of 26 small letters
password += (char)currentValue;
break;
//Cases to generate capital letters
case 4:
case 5:
case 6:
currentValue = randomGenerator.nextInt(26);
currentValue += CAPITAL_LETTERS_BASE_VALUE;
password += (char)currentValue;
break;
//Cases to generate digits
case 7:
case 8:
case 9:
currentValue = randomGenerator.nextInt(10);
password += currentValue;
break;
}//end of switch()
}//end of for loop
System.out.println(password);
You could add cases for special characters as well I guess.
# 2
Alright, I made a few changes to the code; how's this?
public static String generateTempPassword( int passwordLength, boolean hasSmallLetters, boolean hasCaps, boolean hasDigits, boolean hasSpecialChars)
throws IllegalArgumentException
{
if ( !hasSmallLetters & !hasCaps & !hasDigits & !hasSpecialChars )
{
throw new IllegalArgumentException("Atleast one selector for password contents must be true");
}
if ( passwordLength <= 0 )
{
throw new IllegalArgumentException("Password length cannot be negative");
}
StringBuilder password = new StringBuilder("");
int currentValue = 0;
String [] allowedSpecialCharacters = {"!", "#", "$", "%", "&", "*"};
Random randomGenerator = new Random();
for ( int i = 0; password.length() < passwordLength; i++ )
{
switch ( (int) (Math.random()*10))
{
//Cases to generate small case letters
case 0:
case 1:
case 2:
if ( !hasSmallLetters )
continue;
currentValue = randomGenerator.nextInt(26);
currentValue += SMALL_LETTERS_BASE_VALUE;
password.append((char)currentValue);
break;
//Cases to generate capital letters
case 3:
case 4:
case 5:
if ( !hasCaps )
continue;
currentValue = randomGenerator.nextInt(26);
currentValue += CAPITAL_LETTERS_BASE_VALUE;
password.append((char)currentValue);
break;
//Cases to generate digits
case 6:
case 7:
if ( !hasDigits )
continue;
currentValue = randomGenerator.nextInt(10);
password.append(currentValue);
break;
//Cases for special characters using the array of allowable special characters
case 8:
case 9:
if ( !hasSpecialChars )
continue;
currentValue = randomGenerator.nextInt(allowedSpecialCharacters.length);
password.append(allowedSpecialCharacters[currentValue]);
break;
}
}
return password.toString();
}
You can now decide the contents of the password; whether you want special characters or capitals or small case or digits or not. Also, you can specify the length to be generated.
Now, I don't really know how good an algorithm this is and how efficient it is. So if someone who has experience/ ideas about this sort of thing, I'd really appreciate suggestions and improvements.
# 4
> necessary to put all the letters in an array as well?
Well you could; in fact, that's one of the points I'm not sure about. Would it be better to put all the letters ( caps and small ) in an array and then just pick them like I've done for special characters or use the logic that I have?
One point I see in favour of my method is that it's easier to allow selectively including any one of these four categories.
The logic I've used is this:
1. I randomly decide which type of character to append
2. If it's a letter of the alphabet. I generate a random int between 0 to 25 ( indicating one of the 26 letters ) and then either add 97 ( for small letters, which start from ASCII 97 for 'a' and then are consecutively numbered till 'z', which would be 97 + 25 ) or 65 ( for caps, same logic ).
3. If it's a digit, I generate a radom int between 0 to 9 to get a single digit numeral
4. If it's a special char, I generate an int between 0 to the length of the array to get an index into the array and pick a special char randomly
5. I append the current character to the final string
I've also changed the code a bit, using a char [] instead of the String [] for special chars. I now also, allow the invocation with an array of chars so that the user can specify the chars to be used. In case he/ she doesn't, I default to a hardcoded array.
static final int SMALL_LETTERS_BASE_VALUE = 97;
static final int CAPITAL_LETTERS_BASE_VALUE = 65;
//public static void main (String[] args )
//{
//char [] allowedSpecialCharacters = {'!', '$'};
//
//System.out.println(PasswordGenerator.generateTempPassword(7, true, true, true, true, allowedSpecialCharacters));
//}
/**
*@author no.good.at.coding
*
*Generates a (temporary) password the contents of which are decided by the various parameters. If hasSpecialChars is false, this is ignored.
*If hasSpecialChars is true and the passed array of special characters is either null or the length is 0, default special characters '!', '#', '$', '%', '&', '*' will be used
*@param passwordLength The required password length to be generated
*@param hasSmallLetters Whether the generated password should contain small case letters
*@param hasCaps Whether the generated password should contain capital letters
*@param hasDigits Whether the generated password should contain digits
*@param hasSpecialChars Whether the generated password should contain special characters; picked from the array of allowable special characters
*@param allowedSpecialCharacters A list of special characters that are allowed and will be picked from while generating the password
*
*@return The String containing the password generated with contents and length as per parameters passed
*/
public static String generateTempPassword( int passwordLength, boolean hasSmallLetters, boolean hasCaps, boolean hasDigits, boolean hasSpecialChars, char [] allowedSpecialCharacters)
throws IllegalArgumentException
{
////////////////////////////////////////////////////////////CHECK FOR VALID PARAMETERS////////////////////////////////////////////////////////////
if ( !hasSmallLetters & !hasCaps & !hasDigits & !hasSpecialChars ) //check that atleast one boolean is true
{
throw new IllegalArgumentException("Atleast one selector for password contents must be true");
}
if ( passwordLength <= 0 ) //check if length is valid
{
throw new IllegalArgumentException("Password length cannot be negative");
}
if ( hasSpecialChars & ( allowedSpecialCharacters == null || allowedSpecialCharacters.length == 0) )
allowedSpecialCharacters = new char [] {'!', '#', '$', '%', '&', '*'};//use default values for special characters
////////////////////////////////////////////////////////////END CHECK FOR VALID PARAMETERS////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////INITIALISE VARIABLES////////////////////////////////////////////////////////////
StringBuilder password = new StringBuilder("");
int currentValue = 0; //to hold currently generated random value
Random randomGenerator = new Random();
////////////////////////////////////////////////////////////END INITIALISE VARIABLES////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////LOOP////////////////////////////////////////////////////////////
//to create a string of specified length
for ( int i = 0; password.length() < passwordLength; i++ )
{
////////////////////////////////////////////////////////////SWITCH////////////////////////////////////////////////////////////
//to randomly decide whether current character to be added should be a small case, cap, digit or special char
switch ( (int) (Math.random()*10))
{
//Cases to generate small case letters, more cases than digits and special chars to get more occurences
case 0:
case 1:
case 2:
case 3:
if ( !hasSmallLetters )
continue; //if this was set to be not included then continue
currentValue = randomGenerator.nextInt(26);
currentValue += SMALL_LETTERS_BASE_VALUE; //convert to a valid ASCII value for a-z
password.append((char)currentValue);
break;
//Cases to generate capital letters, more cases than digits and special chars to get more occurences
case 4:
case 5:
case 6:
case 7:
if ( !hasCaps )
continue;//if this was set to be not included then continue
currentValue = randomGenerator.nextInt(26);
currentValue += CAPITAL_LETTERS_BASE_VALUE;//convert to a valid ASCII value for A-Z
password.append((char)currentValue);
break;
//Cases for digits, only 1 case to give lower probability and fewer occurences
case 8:
if ( !hasDigits )
continue;//if this was set to be not included then continue
currentValue = randomGenerator.nextInt(10);
password.append(currentValue);
break;
//Cases for special characters, only 1 case to give lower probability and fewer occurences
case 9:
if ( !hasSpecialChars )
continue;//if this was set to be not included then continue
currentValue = randomGenerator.nextInt(allowedSpecialCharacters.length);
password.append(allowedSpecialCharacters[currentValue]);
break;
}//end of switch
////////////////////////////////////////////////////////////END SWITCH////////////////////////////////////////////////////////////
}//end of for
////////////////////////////////////////////////////////////END LOOP////////////////////////////////////////////////////////////
return password.toString();
}//end of generateTempPassword()