## Random password generator with numbers and special characters

I saw many password generators but none of them did what I needed. Also it was often not random enough and/or unnesessary complex. So I created my own password generator. It has parameters for the lenght of the password, the minimum lowercase, uppercase, numbers and special characters.

The algorithm that I devised for this method is as follows.

In this example I use these parameters:

• Password length minimum: 8 / maximum: 15
• Minimum lowercase: 2
• Minimum uppercase: 2
• Minimum numbers: 1
• Minimum special characters: 1

Steps:

1. Determine the length of the password within the given range (for example 13 is a random value within the range 8-15)
2. Get 2 random lower characters (for example: va)
3. Get 2 random upper characters (for example: TK)
4. Get 1 random number character (for example: 3)
5. Get 1 random lower character (for example: @)
6. We have 6 characters already, so we add 7 random characters from all catagories to make 13 the right password length (for example: Jt4\$7ABr)
7. Concat all characters to 1 string (this example: vaTK3@Jt4\$7ABr)
8. Shuffle the characters (for example: KtBTA74arJ@\$v3)

This is translated in code to:

``````

// Get the required characters of each catagory and add random charactes of all catagories
var minimumChars = GetRandomString(AllLowerCaseChars, MinimumLowerCaseChars) +
GetRandomString(AllUpperCaseChars, MinimumUpperCaseChars) +
GetRandomString(AllNumericChars, MinimumNumericChars) +
GetRandomString(AllSpecialChars, MinimumSpecialChars);
var rest = GetRandomString(AllAvailableChars, lengthOfPassword - minimumChars.Length);
var unshuffeledResult = minimumChars + rest;

// Shuffle the result so the order of the characters are unpredictable
var result = unshuffeledResult.ShuffleTextSecure();
return result;

```
```

That's is the core of the algorithm, but (without C# 6.0) storing an checking the parameters is much more code.

This is the full class:

``````
{
public int MinimumLengthPassword { get; private set; }
public int MaximumLengthPassword { get; private set; }
public int MinimumLowerCaseChars { get; private set; }
public int MinimumUpperCaseChars { get; private set; }
public int MinimumNumericChars { get; private set; }
public int MinimumSpecialChars { get; private set; }

public static string AllLowerCaseChars { get; private set; }
public static string AllUpperCaseChars { get; private set; }
public static string AllNumericChars { get; private set; }
public static string AllSpecialChars { get; private set; }

private readonly RandomSecureVersion _randomSecure = new RandomSecureVersion();
private int _minimumNumberOfChars;

{
// Ranges not using confusing characters
AllLowerCaseChars = GetCharRange('a', 'z', exclusiveChars: "ilo");
AllUpperCaseChars = GetCharRange('A', 'Z', exclusiveChars: "IO");
AllNumericChars = GetCharRange('2', '9');
AllSpecialChars = "!@#%*()\$?+-=";
}

int minimumUpperCaseChars = 1,int minimumNumericChars = 1,int minimumSpecialChars = 1)
{
{
throw new ArgumentException("The minimumlength is smaller than 1.","minimumLengthPassword");
}

{
throw new ArgumentException("The minimumLength is bigger than the maximum length.","minimumLengthPassword");
}

if (minimumLowerCaseChars < 0)
{
throw new ArgumentException("The minimumLowerCase is smaller than 0.", "minimumLowerCaseChars");
}

if (minimumUpperCaseChars < 0)
{
throw new ArgumentException("The minimumUpperCase is smaller than 0.","minimumUpperCaseChars");
}

if (minimumNumericChars < 0)
{
throw new ArgumentException("The minimumNumeric is smaller than 0.", "minimumNumericChars");
}

if (minimumSpecialChars < 0)
{
throw new ArgumentException("The minimumSpecial is smaller than 0.", "minimumSpecialChars");
}

_minimumNumberOfChars = minimumLowerCaseChars + minimumUpperCaseChars + minimumNumericChars + minimumSpecialChars;

{
throw new ArgumentException(
"The minimum length ot the password is smaller than the sum " +
"of the minimum characters of all catagories.",
}

MinimumLowerCaseChars = minimumLowerCaseChars;
MinimumUpperCaseChars = minimumUpperCaseChars;
MinimumNumericChars = minimumNumericChars;
MinimumSpecialChars = minimumSpecialChars;

_allAvailableChars =
OnlyIfOneCharIsRequired(minimumLowerCaseChars, AllLowerCaseChars) +
OnlyIfOneCharIsRequired(minimumUpperCaseChars, AllUpperCaseChars) +
OnlyIfOneCharIsRequired(minimumNumericChars, AllNumericChars) +
OnlyIfOneCharIsRequired(minimumSpecialChars, AllSpecialChars);
}

private string OnlyIfOneCharIsRequired(int minimum, string allChars)
{
return minimum > 0 || _minimumNumberOfChars == 0 ? allChars : string.Empty;
}

public string Generate()
{

// Get the required number of characters of each catagory and
// add random charactes of all catagories
var minimumChars = GetRandomString(AllLowerCaseChars, MinimumLowerCaseChars) +
GetRandomString(AllUpperCaseChars, MinimumUpperCaseChars) +
GetRandomString(AllNumericChars, MinimumNumericChars) +
GetRandomString(AllSpecialChars, MinimumSpecialChars);
var rest = GetRandomString(_allAvailableChars, lengthOfPassword - minimumChars.Length);
var unshuffeledResult = minimumChars + rest;

// Shuffle the result so the order of the characters are unpredictable
var result = unshuffeledResult.ShuffleTextSecure();
return result;
}

private string GetRandomString(string possibleChars, int lenght)
{
var result = string.Empty;
for (var position = 0; position < lenght; position++)
{
var index = _randomSecure.Next(possibleChars.Length);
result += possibleChars[index];
}
return result;
}

private static string GetCharRange(char minimum, char maximum, string exclusiveChars = "")
{
var result = string.Empty;
for (char value = minimum; value <= maximum; value++)
{
result += value;
}
if (!string.IsNullOrEmpty(exclusiveChars))
{
var inclusiveChars = result.Except(exclusiveChars).ToArray();
result = new string(inclusiveChars);
}
return result;
}
}

```
```

And it uses these extension methods:

``````
internal static class Extensions
{
private static readonly Lazy<RandomSecureVersion> RandomSecure = new Lazy<RandomSecureVersion>(() => new RandomSecureVersion());
public static IEnumerable<T>ShuffleSecure<T>(this IEnumerable<T>source)
{
var sourceArray = source.ToArray();
for (int counter = 0; counter < sourceArray.Length; counter++)
{
int randomIndex = RandomSecure.Value.Next(counter, sourceArray.Length);
yield return sourceArray[randomIndex];

sourceArray[randomIndex] = sourceArray[counter];
}
}

public static string ShuffleTextSecure(this string source)
{
var shuffeldChars = source.ShuffleSecure().ToArray();
return new string(shuffeldChars);
}
}

```
```

And it uses this secure version of the regular Random class:

``````
internal class RandomSecureVersion
{
private readonly RNGCryptoServiceProvider _rngProvider = new RNGCryptoServiceProvider();

public int Next()
{
var randomBuffer = new byte[4];
_rngProvider.GetBytes(randomBuffer);
var result = BitConverter.ToInt32(randomBuffer, 0);
return result;
}

public int Next(int maximumValue)
{
// Do not use Next() % maximumValue because the distribution is not OK
return Next(0, maximumValue);
}

public int Next(int minimumValue, int maximumValue)
{
var seed = Next();

//  Generate uniformly distributed random integers within a given range.
return new Random(seed).Next(minimumValue, maximumValue);
}
}

```
```

The last class is also handy to use in other situations if you are familiar with the Random class but need more security.