ASP.NET Identity : Generate random password

Is there any built in function that creates random passwords ?
Asp.net simple memebership used to have a similar method

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Although I’m a bit late to the party, I would like to share the helper method I put together to handle these kind of scenarios in an ASP.NET Core compatible way.

The function below ensures a decent char distribution, adding the required character types randomly within the string and not altering the required length (unless edge-case scenarios with lots of required unique chars, which was meant by design). It also features the 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
            "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="80a1c0">[email protected]</a>$?_-"                        // 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 a PasswordOptions object as parameter, which is shipped by the Microsoft.AspNetCore.Identity assembly, but you can easily replace it with a two int / four bool parameter group (or POCO class) if you don’t have that package installed.

In the likely case you have it in your ASP.NET Core project, you can use the exact same object used in the ConfigureService method of the Startup class when defining the 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>();

[...]

For additional details regarding this helper function you can also read this post on my blog.

Method 2

If you are using .NET Framework and System.Web.Security.Membership is available to you:

Check here:

 string password = Membership.GeneratePassword(12, 1);

Note that this class is not available in .NET Standard or .NET Core.

Method 3

ASP.NET Identity does not have a generate password method.

I’m not sure of your exact use case, but I believe the preferred approach would be to send the user a reset password link that allows the user to enter their own password. This is generally considered more secure than sending out a generated password in plain text.

See the Reset Password section in this tutorial:
http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity

Method 4

I know this is a bit of an old question, and there have been others who put out source for randomly generating passwords but
Membership.GeneratePassword is implemented like this:

Luckily this is licensed under The MIT License https://github.com/Microsoft/referencesource/blob/master/LICENSE.txt

public class PasswordStore
{
        private static readonly char[] Punctuations = "<a href="https://getridbug.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="052445">[email protected]</a>#$%^&*()_-+=[{]};:>|./?".ToCharArray();
        private static readonly char[] StartingChars = new char[] { '<', '&' };
        /// <summary>Generates a random password of the specified length.</summary>
        /// <returns>A random password of the specified length.</returns>
        /// <param name="length">The number of characters in the generated password. The length must be between 1 and 128 characters. </param>
        /// <param name="numberOfNonAlphanumericCharacters">The minimum number of non-alphanumeric characters (such as @, #, !, %, &amp;, and so on) in the generated password.</param>
        /// <exception cref="T:System.ArgumentException">
        /// <paramref name="length" /> is less than 1 or greater than 128 -or-<paramref name="numberOfNonAlphanumericCharacters" /> is less than 0 or greater than <paramref name="length" />. </exception>
        public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters)
        {
            if (length < 1 || length > 128)
                throw new ArgumentException("password_length_incorrect", nameof(length));
            if (numberOfNonAlphanumericCharacters > length || numberOfNonAlphanumericCharacters < 0)
                throw new ArgumentException("min_required_non_alphanumeric_characters_incorrect", nameof(numberOfNonAlphanumericCharacters));
            string s;
            int matchIndex;
            do
            {
                var data = new byte[length];
                var chArray = new char[length];
                var num1 = 0;
                new RNGCryptoServiceProvider().GetBytes(data);
                for (var index = 0; index < length; ++index)
                {
                    var num2 = (int)data[index] % 87;
                    if (num2 < 10)
                        chArray[index] = (char)(48 + num2);
                    else if (num2 < 36)
                        chArray[index] = (char)(65 + num2 - 10);
                    else if (num2 < 62)
                    {
                        chArray[index] = (char)(97 + num2 - 36);
                    }
                    else
                    {
                        chArray[index] = Punctuations[num2 - 62];
                        ++num1;
                    }
                }
                if (num1 < numberOfNonAlphanumericCharacters)
                {
                    var random = new Random();
                    for (var index1 = 0; index1 < numberOfNonAlphanumericCharacters - num1; ++index1)
                    {
                        int index2;
                        do
                        {
                            index2 = random.Next(0, length);
                        }
                        while (!char.IsLetterOrDigit(chArray[index2]));
                        chArray[index2] = Punctuations[random.Next(0, Punctuations.Length)];
                    }
                }
                s = new string(chArray);
            }
            while (IsDangerousString(s, out matchIndex));
            return s;
        }

        internal static bool IsDangerousString(string s, out int matchIndex)
        {
            //bool inComment = false;
            matchIndex = 0;

            for (var i = 0; ;)
            {

                // Look for the start of one of our patterns 
                var n = s.IndexOfAny(StartingChars, i);

                // If not found, the string is safe
                if (n < 0) return false;

                // If it's the last char, it's safe 
                if (n == s.Length - 1) return false;

                matchIndex = n;

                switch (s[n])
                {
                    case '<':
                        // If the < is followed by a letter or '!', it's unsafe (looks like a tag or HTML comment)
                        if (IsAtoZ(s[n + 1]) || s[n + 1] == '!' || s[n + 1] == '/' || s[n + 1] == '?') return true;
                        break;
                    case '&':
                        // If the & is followed by a #, it's unsafe (e.g. S) 
                        if (s[n + 1] == '#') return true;
                        break;
                }

                // Continue searching
                i = n + 1;
            }
        }

        private static bool IsAtoZ(char c)
        {
            if ((int)c >= 97 && (int)c <= 122)
                return true;
            if ((int)c >= 65)
                return (int)c <= 90;
            return false;
        }
    }

Method 5

Membership.GeneratePassword() create a password that isn’t compliant with Identity validator.

I have written a simple function that consider UserManager Validator for creating a right random password to assign to user.

It simply generates random chars and check if chars satisfy Validator requirements. If the requirements aren’t satisfied, it appends the remaining chars to satisfy rules.

private string GeneratePassword(MessagePasswordValidator validator)
{
    if (validator == null)
        return null;

    bool requireNonLetterOrDigit = validator.RequireNonLetterOrDigit;
    bool requireDigit = validator.RequireDigit;
    bool requireLowercase = validator.RequireLowercase;
    bool requireUppercase = validator.RequireUppercase;

    string randomPassword = string.Empty;

    int passwordLength = validator.RequiredLength;

    Random random = new Random();
    while (randomPassword.Length != passwordLength)
    {
        int randomNumber = random.Next(48, 122);  // >= 48 && < 122 
        if (randomNumber == 95 || randomNumber == 96) continue;  // != 95, 96 _'

        char c = Convert.ToChar(randomNumber);

        if (requireDigit)
            if (char.IsDigit(c))
                requireDigit = false;

        if (requireLowercase)
            if (char.IsLower(c))
                requireLowercase = false;

        if (requireUppercase)
            if (char.IsUpper(c))
                requireUppercase = false;

        if (requireNonLetterOrDigit)
            if (!char.IsLetterOrDigit(c))
                requireNonLetterOrDigit = false;

        randomPassword += c;
    }

    if (requireDigit)
        randomPassword += Convert.ToChar(random.Next(48, 58));  // 0-9

    if (requireLowercase)
        randomPassword += Convert.ToChar(random.Next(97, 123));  // a-z

    if (requireUppercase)
        randomPassword += Convert.ToChar(random.Next(65, 91));  // A-Z

    if (requireNonLetterOrDigit)
        randomPassword += Convert.ToChar(random.Next(33, 48));  // symbols !"#$%&'()*+,-./

    return randomPassword;
}

and calling:
string password = GeneratePassword(UserManager.PasswordValidator as MessagePasswordValidator);

Method 6

public static class PasswordCombinationType
{
    public const int Any = 1;
    public const int AtLeast2Types = 2;
    public const int AtLeast3Types = 3;
    public const int All4Types = 4;
}
public class PasswordStore
{

    /// <summary>
    /// Generate Random Password
    /// </summary>
    /// <param name="length">Minimum length of password </param>
    /// <param name="minLowerCaseCharacter">Minimum Lower Case Character</param>
    /// <param name="minUpperCaseCharacter">Minimum Upper Case Character</param>
    /// <param name="MinSpecialCharacter">Minimum Special Character</param>
    /// <param name="minDigit">Minimum Digit</param>
    /// <param name="passwordCombinationTypeId"> 1= Any, 2 =Character only , 3= Character with digit ,4 = Character and Special Character with  digit</param>
    /// <returns>Random Password</returns>
    public static string GeneratePassword(int passwordLength,
        int minLowerCaseCharacter,
        int minUpperCaseCharacter,
        int MinSpecialCharacter,
        int minDigit,
        int passwordCombinationTypeId)
    {
        string randomPassword = string.Empty;
        Random random = new Random();
        int minDigitCount = 0;
        int minLowerCaseCharacterCount = 0;
        int minUpperCaseCharacterCount = 0;
        int minSpecialCharacterCount = 0;

        do
        {
            switch (passwordCombinationTypeId)
            {
                case PasswordCombinationType.Any:
                case PasswordCombinationType.All4Types:
                    RandomDigit(minDigit, ref randomPassword, random, ref minDigitCount);
                    RandomLowerCaseCharacter(minLowerCaseCharacter, ref randomPassword, random, ref minLowerCaseCharacterCount);
                    RandomUpperCaseCharacter(minUpperCaseCharacter, ref randomPassword, random, ref minUpperCaseCharacterCount);
                    RandomSpecialCharacter(MinSpecialCharacter, ref randomPassword, random, ref minSpecialCharacterCount);
                    break;
                case PasswordCombinationType.AtLeast2Types:
                    RandomLowerCaseCharacter(minLowerCaseCharacter, ref randomPassword, random, ref minLowerCaseCharacterCount);
                    RandomUpperCaseCharacter(minUpperCaseCharacter, ref randomPassword, random, ref minUpperCaseCharacterCount);
                    break;
                case PasswordCombinationType.AtLeast3Types:
                    RandomDigit(minDigit, ref randomPassword, random, ref minDigitCount);
                    RandomLowerCaseCharacter(minLowerCaseCharacter, ref randomPassword, random, ref minLowerCaseCharacterCount);
                    RandomUpperCaseCharacter(minUpperCaseCharacter, ref randomPassword, random, ref minUpperCaseCharacterCount);
                    break;
            }
            if (passwordLength != randomPassword.Length)
            {
                randomPassword += Convert.ToChar(random.Next(33, 126));
            }
        } while (passwordLength != randomPassword.Length);
        return randomPassword;


    }
    internal static void RandomLowerCaseCharacter(int minLowerCaseCharacter, ref string randomPassword, Random random, ref int minLowerCaseCharacterCount)
    {
        while (minLowerCaseCharacter != minLowerCaseCharacterCount)
        {
            randomPassword += Convert.ToChar(random.Next(97, 123));  // a-z
            minLowerCaseCharacterCount++;
        }
    }
    internal static void RandomDigit(int minDigit, ref string randomPassword, Random random, ref int minDigitCount)
    {
        while (minDigit != minDigitCount)
        {
            randomPassword += Convert.ToChar(random.Next(48, 58));  // 0-9
            minDigitCount++;
        }
    }
    internal static void RandomUpperCaseCharacter(int minUpperCaseCharacter, ref string randomPassword, Random random, ref int minUpperCaseCharacterCount)
    {
        while (minUpperCaseCharacter != minUpperCaseCharacterCount)
        {
            randomPassword += Convert.ToChar(random.Next(65, 91));  // A-Z
            minUpperCaseCharacterCount++;
        }
    }
    internal static void RandomSpecialCharacter(int MinSpecialCharacter, ref string randomPassword, Random random, ref int minSpecialCharacterCount)
    {
        while (MinSpecialCharacter != minSpecialCharacterCount)
        {
            randomPassword += Convert.ToChar(random.Next(33, 48));  // symbols !"#$%&'()*+,-./
            minSpecialCharacterCount++;
        }
    }

}

Method 7

https://msdn.microsoft.com/ru-ru/library/system.guid.newguid(v=vs.110).aspx
Check this out. GUID should work just fine (just remove all the ‘-‘ from it and cut required number if characters)


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x