public class PasswordOptions
public bool RequireNonAlphanumeric { get; set; }
public bool RequireDigit { get; set; }
public bool RequireLowercase { get; set; }
public bool RequireUppercase { get; set; }
public uint RequiredLength { get; set; } = 20;
public static PasswordOptions Strongest() =>
RequireNonAlphanumeric = true,
public class PasswordGenerator
private readonly PasswordOptions _options;
private readonly Random _random;
private uint _currentGenerationLength;
private bool _currentGenerationShouldIncludeNonAlphanumeric;
private bool _currentGenerationShouldIncludeDigit;
private bool _currentGenerationShouldIncludeLowercase;
private bool _currentGenerationShouldIncludeUppercase;
public PasswordGenerator() : this(PasswordOptions.Strongest())
public PasswordGenerator(PasswordOptions options)
SetRequirementsBasedOnOptions();
var password = new StringBuilder();
GeneratePasswordOfMinimumSize(password);
AddMissingRequirements(password);
return password.ToString();
private void AddMissingRequirements(StringBuilder password)
AddNonAlphanumericIfMissing(password);
AddDigitIfMissing(password);
AddLowercaseIfMissing(password);
AddUppercaseIfMissing(password);
private void GeneratePasswordOfMinimumSize(StringBuilder password)
while (password.Length < _currentGenerationLength)
updateRequirementsBasedOnCharacter(c);
private void AddUppercaseIfMissing(StringBuilder password)
if (_currentGenerationShouldIncludeUppercase)
password.Append(RandomUppercase());
private void AddLowercaseIfMissing(StringBuilder password)
if (_currentGenerationShouldIncludeLowercase)
password.Append(RandomLowercase());
private void AddDigitIfMissing(StringBuilder password)
if (_currentGenerationShouldIncludeDigit)
password.Append(RandomDigit());
private void AddNonAlphanumericIfMissing(StringBuilder password)
if (_currentGenerationShouldIncludeNonAlphanumeric)
password.Append(RandomNonAlphanumeric());
private void SetRequirementsBasedOnOptions()
_currentGenerationLength = _options.RequiredLength;
_currentGenerationShouldIncludeNonAlphanumeric = _options.RequireNonAlphanumeric;
_currentGenerationShouldIncludeDigit = _options.RequireDigit;
_currentGenerationShouldIncludeLowercase = _options.RequireLowercase;
_currentGenerationShouldIncludeUppercase = _options.RequireUppercase;
return (char) _random.Next(32, 126);
private void updateRequirementsBasedOnCharacter(char c)
_currentGenerationShouldIncludeDigit = false;
else if (char.IsLower(c))
_currentGenerationShouldIncludeLowercase = false;
else if (char.IsUpper(c))
_currentGenerationShouldIncludeUppercase = false;
else if (!char.IsLetterOrDigit(c))
_currentGenerationShouldIncludeNonAlphanumeric = false;
private char RandomUppercase()
return (char) _random.Next(65, 91);
private char RandomLowercase()
return (char) _random.Next(97, 123);
private char RandomDigit()
return (char) _random.Next(48, 58);
private char RandomNonAlphanumeric()
return (char) _random.Next(33, 48);
public static void Main()
var generator = new PasswordGenerator();
var password = generator.Generate();
Console.WriteLine($"Password is: {password}");