Title: Use cryptographic methods to generate a random password in C#
Lately I've gotten more than a little tired of having to generate random passwords that obey all sorts of stupid rules for various web sites. Who cares if I use a strong password on a web site that just sends me spam?
This program lets you generate cryptographically random passwords automatically. In my next post I'll show you how to make a program to manage passwords so you don't have to remember the strong but unmemorable passwords this program generates.
Enter the characteristics that you want the password to have such as its length and whether it should contain letters, numbers, special characters, and so forth. Then click Generate to create a password.
The program contains some miscellaneous code to make the user interface more friendly. For example, if you check one of the "Required" check boxes, the program automatically checks the corresponding "allowed" check box (because if something is required then it must be allowed). Similarly if you uncheck an "allowed" box the program unchecks the corresponding "required" box. All that code is fairly long and uninteresting, so it isn't shown here. Download the example to see it in all its glory.
The following code shows the bulk of how the program generates passwords.
// Generate a password that meets the reuirements.
private string RandomPassword()
{
const string LOWER = "abcdefghijklmnopqrstuvwxyz";
const string UPPER = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string NUMBER = "0123456789";
const string SPECIAL = @"~!@#$%^&*():;[]{}<>,.?/\|";
string other = txtOther.Text;
if (chkRequireOther.Checked && (other.Length < 1))
{
MessageBox.Show(
"You cannot require characters from a blank string.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
txtOther.Focus();
return txtPassword.Text;
}
// Make a list of allowed characters.
string allowed = "";
if (chkAllowLowercase.Checked) allowed += LOWER;
if (chkAllowUppercase.Checked) allowed += UPPER;
if (chkAllowNumber.Checked) allowed += NUMBER;
if (chkAllowSpecial.Checked) allowed += SPECIAL;
if (chkAllowUnderscore.Checked) allowed += "_";
if (chkAllowSpace.Checked) allowed += " ";
if (chkAllowOther.Checked) allowed += other;
// Pick the number of characters.
int min_chars = int.Parse(txtMinLength.Text);
int max_chars = int.Parse(txtMaxLength.Text);
int num_chars = Crypto.RandomInteger(min_chars, max_chars);
// Satisfy requirements.
string password = "";
if (chkRequireLowercase.Checked &&
(password.IndexOfAny(LOWER.ToCharArray()) == -1))
password += RandomChar(LOWER);
if (chkRequireUppercase.Checked &&
(password.IndexOfAny(UPPER.ToCharArray()) == -1))
password += RandomChar(UPPER);
if (chkRequireNumber.Checked &&
(password.IndexOfAny(NUMBER.ToCharArray()) == -1))
password += RandomChar(NUMBER);
if (chkRequireSpecial.Checked &&
(password.IndexOfAny(SPECIAL.ToCharArray()) == -1))
password += RandomChar(SPECIAL);
if (chkRequireUnderscore.Checked &&
(password.IndexOfAny("_".ToCharArray()) == -1))
password += "_";
if (chkRequireSpace.Checked &&
(password.IndexOfAny(" ".ToCharArray()) == -1))
password += " ";
if (chkRequireOther.Checked &&
(password.IndexOfAny(other.ToCharArray()) == -1))
password += RandomChar(other);
// Add the remaining characters randomly.
while (password.Length < num_chars)
password += allowed.Substring(
Crypto.RandomInteger(0, allowed.Length - 1), 1);
// Randomize (to mix up the required characters at the front).
password = RandomizeString(password);
return password;
}
The code begins by defining some strings containing different types of characters: uppercase and lowercase letters, numbers, and special. It sets the string "other" equal to any characters you enter in the text box beside the bottom check boxes. The program then checks that the "other" string is non-blank if you required characters from that text box.
Next, the program builds a string containing all of the allowed characters. It gets the minimum and maximum password length and uses the Crypto.RandomInteger method to pick a random password length. (For information about how that method works, see my post Use a cryptographic random number generator in C#.)
The code then loops through the requirements and adds a random character from each required category. The RandomChar method it uses to pick a random character from a string is described shortly. After satisfying the requirements, the code adds random characters from any category until the password has the desired length.
Next the program randomizes the password to mix up any required characters that were placed at the beginning. (The RandomizeString method is also described shortly.) Otherwise you would know that the password must begin with a lowercase letter, uppercase letter, number, and so forth (if those are required).
Finally the code returns the password.
The following code shows the RandomChar method.
// Return a random character from a string.
private string RandomChar(string str)
{
return str.Substring(Crypto.RandomInteger(0, str.Length - 1), 1);
}
This method simply uses the Crypto.RandomInteger method to pick a random number to use as the index of a character in the string. It then returns the corresponding character.
The following code shows the RandomizeString method.
// Return a random permutation of a string.
private string RandomizeString(string str)
{
string result = "";
while (str.Length > 0)
{
// Pick a random character.
int i = Crypto.RandomInteger(0, str.Length - 1);
result += str.Substring(i, 1);
str = str.Remove(i, 1);
}
return result;
}
This method repeatedly picks a random character in the string, adds it to the result string, and removes it from the original string. It repeats those steps until the original string is empty. The result is a string that contains the original string's characters but in a random order.
Download the example to experiment with it and to see additional details.
|