Although I was a bit late for the party, I would like to share a helper method that I put together to handle these scripts in an ASP.NET compatible kernel.
The function below provides a decent char distribution by adding arbitrary character types to the string and not changing the required length (if only extreme cases with a lot of unique characters needed, which was implied by the design). It also supports support for the RequiredUniqueChars rule, which is one of the strength requirements available for the ASP.NET Core Identity framework.
/// <summary> /// Generates a Random Password /// respecting the given strength requirements. /// </summary> /// <param name="opts">A valid PasswordOptions object /// containing the password strength requirements.</param> /// <returns>A random password</returns> public static string GenerateRandomPassword(PasswordOptions opts = null) { if (opts == null) opts = new PasswordOptions() { RequiredLength = 8, RequiredUniqueChars = 4, RequireDigit = true, RequireLowercase = true, RequireNonAlphanumeric = true, RequireUppercase = true }; string[] randomChars = new[] { "ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase "abcdefghijkmnopqrstuvwxyz", // lowercase "0123456789", // digits " !@ $?_-" // non-alphanumeric }; Random rand = new Random(Environment.TickCount); List<char> chars = new List<char>(); if (opts.RequireUppercase) chars.Insert(rand.Next(0, chars.Count), randomChars[0][rand.Next(0, randomChars[0].Length)]); if (opts.RequireLowercase) chars.Insert(rand.Next(0, chars.Count), randomChars[1][rand.Next(0, randomChars[1].Length)]); if (opts.RequireDigit) chars.Insert(rand.Next(0, chars.Count), randomChars[2][rand.Next(0, randomChars[2].Length)]); if (opts.RequireNonAlphanumeric) chars.Insert(rand.Next(0, chars.Count), randomChars[3][rand.Next(0, randomChars[3].Length)]); for (int i = chars.Count; i < opts.RequiredLength || chars.Distinct().Count() < opts.RequiredUniqueChars; i++) { string rcs = randomChars[rand.Next(0, randomChars.Length)]; chars.Insert(rand.Next(0, chars.Count), rcs[rand.Next(0, rcs.Length)]); } return new string(chars.ToArray()); }
The function takes the PasswordOptions object as a parameter, which is sent using the Microsoft.AspNetCore.Identity assembly, but you can easily replace it with two groups of int / four bool parameters (or the POCO class) if you do not have this package installed.
In the likely case that you have in your ASP.NET Core project, you can use the same object that was used with the ConfigureService method of the Startup class to determine password requirements:
[...] // Add ASP.NET Identity support services.AddIdentity<ApplicationUser, IdentityRole>( opts => { opts.Password.RequireDigit = true; opts.Password.RequireLowercase = true; opts.Password.RequireUppercase = true; opts.Password.RequireNonAlphanumeric = false; opts.Password.RequiredLength = 7; }) .AddEntityFrameworkStores<ApplicationDbContext>(); [...]
You can also read more about this helper function here .