Skip to content

Instantly share code, notes, and snippets.

@alexsandro-xpt
Created December 6, 2018 23:06
Show Gist options
  • Select an option

  • Save alexsandro-xpt/8a58b9b94f01d178b335e93020ed53c2 to your computer and use it in GitHub Desktop.

Select an option

Save alexsandro-xpt/8a58b9b94f01d178b335e93020ed53c2 to your computer and use it in GitHub Desktop.
//Written by Paul Seal. Licensed under MIT. Free for private and commercial uses.
using System;
using System.Text.RegularExpressions;
using CodeShare.Library.Passwords;
public class Program
{
public static void Main()
{
bool includeLowercase = true;
bool includeUppercase = true;
bool includeNumeric = true;
bool includeSpecial = false;
bool includeSpaces = false;
int lengthOfPassword = 16;
string password = PasswordGenerator.GeneratePassword(includeLowercase, includeUppercase, includeNumeric, includeSpecial, includeSpaces, lengthOfPassword);
while(!PasswordGenerator.PasswordIsValid(includeLowercase, includeUppercase, includeNumeric, includeSpecial, includeSpaces, password))
{
password = PasswordGenerator.GeneratePassword(includeLowercase, includeUppercase, includeNumeric, includeSpecial, includeSpaces, lengthOfPassword);
}
Console.WriteLine(password);
}
}
namespace CodeShare.Library.Passwords
{
public static class PasswordGenerator
{
/// <summary>
/// Generates a random password based on the rules passed in the parameters
/// </summary>
/// <param name="includeLowercase">Bool to say if lowercase are required</param>
/// <param name="includeUppercase">Bool to say if uppercase are required</param>
/// <param name="includeNumeric">Bool to say if numerics are required</param>
/// <param name="includeSpecial">Bool to say if special characters are required</param>
/// <param name="includeSpaces">Bool to say if spaces are required</param>
/// <param name="lengthOfPassword">Length of password required. Should be between 8 and 128</param>
/// <returns></returns>
public static string GeneratePassword(bool includeLowercase, bool includeUppercase, bool includeNumeric, bool includeSpecial, bool includeSpaces, int lengthOfPassword)
{
const int MAXIMUM_IDENTICAL_CONSECUTIVE_CHARS = 2;
const string LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
const string UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const string NUMERIC_CHARACTERS = "0123456789";
const string SPECIAL_CHARACTERS = @"!#$%&*@\";
const string SPACE_CHARACTER = " ";
const int PASSWORD_LENGTH_MIN = 8;
const int PASSWORD_LENGTH_MAX = 128;
if (lengthOfPassword < PASSWORD_LENGTH_MIN || lengthOfPassword > PASSWORD_LENGTH_MAX)
{
return "Password length must be between 8 and 128.";
}
string characterSet = "";
if (includeLowercase)
{
characterSet += LOWERCASE_CHARACTERS;
}
if (includeUppercase)
{
characterSet += UPPERCASE_CHARACTERS;
}
if (includeNumeric)
{
characterSet += NUMERIC_CHARACTERS;
}
if (includeSpecial)
{
characterSet += SPECIAL_CHARACTERS;
}
if (includeSpaces)
{
characterSet += SPACE_CHARACTER;
}
char[] password = new char[lengthOfPassword];
int characterSetLength = characterSet.Length;
System.Random random = new System.Random();
for (int characterPosition = 0; characterPosition < lengthOfPassword; characterPosition++)
{
password[characterPosition] = characterSet[random.Next(characterSetLength - 1)];
bool moreThanTwoIdenticalInARow =
characterPosition > MAXIMUM_IDENTICAL_CONSECUTIVE_CHARS
&& password[characterPosition] == password[characterPosition - 1]
&& password[characterPosition - 1] == password[characterPosition - 2];
if (moreThanTwoIdenticalInARow)
{
characterPosition--;
}
}
return string.Join(null, password);
}
/// <summary>
/// Checks if the password created is valid
/// </summary>
/// <param name="includeLowercase">Bool to say if lowercase are required</param>
/// <param name="includeUppercase">Bool to say if uppercase are required</param>
/// <param name="includeNumeric">Bool to say if numerics are required</param>
/// <param name="includeSpecial">Bool to say if special characters are required</param>
/// <param name="includeSpaces">Bool to say if spaces are required</param>
/// <param name="password">Generated password</param>
/// <returns>True or False to say if the password is valid or not</returns>
public static bool PasswordIsValid(bool includeLowercase, bool includeUppercase, bool includeNumeric, bool includeSpecial, bool includeSpaces, string password)
{
const string REGEX_LOWERCASE = @"[a-z]";
const string REGEX_UPPERCASE = @"[A-Z]";
const string REGEX_NUMERIC = @"[\d]";
const string REGEX_SPECIAL = @"([!#$%&*@\\])+";
const string REGEX_SPACE = @"([ ])+";
bool lowerCaseIsValid = !includeLowercase || (includeLowercase && Regex.IsMatch(password, REGEX_LOWERCASE));
bool upperCaseIsValid = !includeUppercase || (includeUppercase && Regex.IsMatch(password, REGEX_UPPERCASE));
bool numericIsValid = !includeNumeric || (includeNumeric && Regex.IsMatch(password, REGEX_NUMERIC));
bool symbolsAreValid = !includeSpecial || (includeSpecial && Regex.IsMatch(password, REGEX_SPECIAL));
bool spacesAreValid = !includeSpaces || (includeSpaces && Regex.IsMatch(password, REGEX_SPACE));
return lowerCaseIsValid && upperCaseIsValid && numericIsValid && symbolsAreValid && spacesAreValid;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment