Create a file RandomPassword.cs or RandomPassword.vb according to your language containing class RandomPassword:
using System;
using System.Security.Cryptography;
namespace Hugon.Security.Cryptography
{
public static class RandomPassword
{
}
}Add variables private by default to set the characters minimum and maximum password generated and the possible characters grouped by type (lowercase, uppercase, numeric and special characters):
private static int DefaultMinPasswordLength = 6;
private static int DefaultMaxPasswordLength = 8;
private static string PasswordCharLCase = "abcdefgijkmnopqrstwxyz";
private static string PasswordCharUCase = "ABCDEFGHJKLMNPQRSTWXYZ";
private static string PasswordCharNumeric = "123456789";
private static string PasswordCharSpecial = "+*%$()=?!][-.,;:_";
Add public variables to define which types of characters will be used to generate the passwords:
public static bool UseLCaseChar = true;
public static bool UseUCaseChar = true;
public static bool UseNumericChar = true;
public static bool UseSpecialChar = false;
Create the function of generating passwords:
public static string Generate(int minLength, int maxLength)
{
if (minLength <= 0 || maxLength <= 0 || minLength > maxLength)
return "";
string s = "";
if (UseLCaseChar)
s += PasswordCharLCase;
if (UseUCaseChar)
s += PasswordCharUCase;
if (UseNumericChar)
s += PasswordCharNumeric;
if (UseSpecialChar)
s += PasswordCharSpecial;
if (s != "")
{
char[][] charGroups = new char[][] { s.ToCharArray() };
int[] charsLeftInGroup = new int[charGroups.Length];
for (int i = 0; i < charsLeftInGroup.Length; i++)
charsLeftInGroup[i] = charGroups[i].Length;
int[] leftGroupsOrder = new int[charGroups.Length];
for (int i = 0; i < leftGroupsOrder.Length; i++)
leftGroupsOrder[i] = i;
byte[] randomBytes = new byte[4];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(randomBytes);
int seed = (randomBytes[0] & 0x7f) << 24 |
randomBytes[1] << 16 |
randomBytes[2] << 8 |
randomBytes[3];
Random random = new Random(seed);
char[] password = null;
if (minLength < maxLength)
password = new char[random.Next(minLength, maxLength + 1)];
else
password = new char[minLength];
int nextCharIdx;
int nextGroupIdx;
int nextLeftGroupsOrderIdx;
int lastCharIdx;
int lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
for (int i = 0; i < password.Length; i++)
{
if (lastLeftGroupsOrderIdx == 0)
nextLeftGroupsOrderIdx = 0;
else
nextLeftGroupsOrderIdx = random.Next(0, lastLeftGroupsOrderIdx);
nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
if (lastCharIdx == 0)
nextCharIdx = 0;
else
nextCharIdx = random.Next(0, lastCharIdx + 1);
password[i] = charGroups[nextGroupIdx][nextCharIdx];
if (lastCharIdx == 0)
charsLeftInGroup[nextGroupIdx] = charGroups[nextGroupIdx].Length;
else
{
if (lastCharIdx != nextCharIdx)
{
char temp = charGroups[nextGroupIdx][lastCharIdx];
charGroups[nextGroupIdx][lastCharIdx] = charGroups[nextGroupIdx][nextCharIdx];
charGroups[nextGroupIdx][nextCharIdx] = temp;
}
charsLeftInGroup[nextGroupIdx]--;
}
if (lastLeftGroupsOrderIdx == 0)
lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
else
{
if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
{
int temp = leftGroupsOrder[lastLeftGroupsOrderIdx];
leftGroupsOrder[lastLeftGroupsOrderIdx] = leftGroupsOrder[nextLeftGroupsOrderIdx];
leftGroupsOrder[nextLeftGroupsOrderIdx] = temp;
}
lastLeftGroupsOrderIdx--;
}
}
return new string(password);
}
else
return "";
}Add two functions to generate passwords overloading the first above. The first of these new functions can be called without parameters of minimum and maximum number of characters that the password generated will contain the default values for, the variables DefaultMinPasswordLength and DefaultMaxPasswordLength will be used for the minimum and maximum. The second accepts a parameter of type integer to be used as minimum and maximum, ie the generated password will be a fixed length:
public static string Generate()
{
return RandomPassword.Generate(DefaultMinPasswordLength, DefaultMaxPasswordLength);
}
public static string Generate(int length)
{
return RandomPassword.Generate(length, length);
}