Membership Generate Password alphanumeric only password?
Asked Answered
C

8

40

How can I use Membership.GeneratePassword to return a password that ONLY contains alpha or numeric characters? The default method will only guarantee a minimum and not a maximum number of non alphanumeric passwords.

Carbonari answered 12/4, 2010 at 20:21 Comment(5)
Why do you want to do this? Special characters are a good thing to have in your password. If (for some bizarre reason beyond my comprehension) you really want one, write your own method to generate it and don't use GeneratePassword.Malone
One reasons is because those generated passwords aren't really globalization friendly. Another reason is that the CEO using the application got mad at the ugly, yet secure generated password and told you change it.Natatorial
Or in my case, the punctuation marks are causing a server error in the API I am calling.Longhair
Or in my case, I've been told that they're more difficult to enter if you're using the keyboard on a mobile device.Vaginitis
In my case, I am generating passwords that are then to be entered into a physical device whose UI does not allow input of most special characters.Tallia
C
62
string newPassword = Membership.GeneratePassword(15, 0);
newPassword = Regex.Replace(newPassword, @"[^a-zA-Z0-9]", m => "9" );

This regular expression will replace all non alphanumeric characters with the numeric character 9.

Carbonari answered 12/4, 2010 at 20:23 Comment(9)
This will lose quite a bit of randomness in your password. Not recommended.Malone
@Matti Possible to replace the "9" with Random.Next(0, 9) integer. Placing non alphanumeric characters into a typical password is typically overkill. A randomly generated password that doesn't use words is fine for many applications. The reason to do this is usability. Many non alpha-numeric characters are easily mistaken or confused or not able to be entered by average user.Carbonari
@Matti It is also possible with this code to then go back and only insert a subset of approved non-alphanumeric characters. I don't see the need for any for many applications though.Carbonari
@Curtis White: I prefer to draw the line where I consider a user fit to user a computer above the ability to read punctuation and use the keyboard correctly.Malone
+1 Not sure why this was voted down. Whether or not you agree w/ the approach taken, this is a great answer to the question.Jeaninejeanlouis
And to comment on whether or not this is secure...using Random.Next() w/ the code above generates a password w/ 7.7e26 possible combinations - I'd say that is still very secure.Jeaninejeanlouis
Use 10 as your maximum since the upper limit is exclusive on the Random.Next method. string newPassword = Membership.GeneratePassword(8, 0); Random rnd = new Random(); newPassword = Regex.Replace(newPassword, @"[^a-zA-Z0-9]", m => rnd.Next(0,10).ToString() );Land
@"[^0-9]" is better then @"[^a-zA-Z0-9]" beacuaes its added some non alphabetical charactersJustness
GeneratePassword may be less than ideal. They use non crypto Random sometimes for non alphanumeric characters. See referencesource.microsoft.com/#System.Web/Security/… So that would result in less distributed usage of non-alphanumeric characters in theory. Looks like someone did that analysis and that does appear to be a reduction in randomness in their current algo for non-alphanumeric chars in some cases see poshhelp.wordpress.com/2017/01/30/…Gerson
K
17

I realised that there may be ways of doing this. The GUID method is great, except it doesn't mix UPPER and lower case alphabets. In my case it produced lower-case only.

So I decided to use the Regex to remove the non-alphas then substring the results to the length that I needed.

string newPassword = Membership.GeneratePassword(50, 0); 

newPassword = Regex.Replace(newPassword, @"[^a-zA-Z0-9]", m => ""); 

newPassword = newPassword.Substring(0, 10);
Kamilah answered 29/5, 2013 at 12:1 Comment(4)
Although unlikely, it is feasible that the initial password generated could contain less than 10 alphanumeric characters, which would then result in ArgumentOutOfRangeException() thrown by the Substring() method.Dichromaticism
I beg to differ @Chris. The 50 in Membership.GeneratePassword specifies the length of the password, not just the MaxLength.Kamilah
@SollyM yes it does. However there is nothing to stop all 50 characters being symbols (i.e. not alphanumeric). It's unlikely, but feasible. If more than 40 were symbols, you would get an exception thrown by the Substring() method in the third line.Dichromaticism
I get what you mean now. Which makes sense. But unlikely due to the next digit being 0. That reduces the occurrence of the non-AlphaNumerics. I am sure technically speaking this could result in an error, but I have been using this code for 9 months without a problem whatsoever.Kamilah
S
15

A simple way to get an 8 character alphanumeric password would be to generate a guid and use that as the basis:

string newPwd = Guid.NewGuid().ToString().Substring(0, 8);

If you need a longer password, just skip over the dash using substrings:

string newPwd = Guid.NewGuid().ToString().Substring(0, 11);
newPwd = newPwd.Substring(0, 8) + newPwd.Substring(9, 2); // to skip the dash.

If you want to make sure the first character is alpha, you could just replace it when needed with a fixed string if (newPwd[0] >= '0' && newPwd[0] <= '9')...

I hope someone can find this helpful. :-)

Selfsealing answered 21/9, 2010 at 21:9 Comment(1)
This is not a good idea. For one, you're reducing your set of possible characters to 16 (instead of 36); for another, guids aren't necessarily random, and depending on the method use to generate the guid the passwords you're creating might be easily predictable. I highly recommend Eric Lippert's series on how guids work for more info about this: blogs.msdn.com/b/ericlippert/archive/2012/04/24/…Rael
H
2

You could also try to generate passwords and concatenate the non alphanumeric characters until you reach the desired password length.

public string GeneratePassword(int length)
{
    var sb = new StringBuilder(length);

    while (sb.Length < length)
    {
        var tmp = System.Web.Security.Membership.GeneratePassword(length, 0);

        foreach(var c in tmp)
        {
            if(char.IsLetterOrDigit(c))
            {
                sb.Append(c);

                if (sb.Length == length)
                {
                    break;
                }
            }
        }
    }

    return sb.ToString();
}
Heteropterous answered 13/9, 2016 at 9:51 Comment(0)
W
2

There is similar approach with breigo's solution. Maybe this is not so effective but so clear and short

string GeneratePassword(int length)
{
     var password = "";
     while (password.Length < length)
     {
          password += string.Concat(Membership.GeneratePassword(1, 0).Where(char.IsLetterOrDigit));
     }
     return password;
}
Windburn answered 17/4, 2017 at 13:47 Comment(0)
U
0

I also prefer the GUID method - here's the short version:

string password = Guid.NewGuid().ToString("N").Substring(0, 8);
Unseat answered 27/4, 2011 at 10:49 Comment(2)
Effectively the same exact answer as Laura's, with a string format specified for no reason (has zero effect).Exchequer
There is the difference that Laura's had to explicitly remove the dashes whereas the format string provided here would let someone get a longer set of characters without removing the dashes manually afterward.Biosynthesis
K
0

Going from @SollyM's answer, putting a while loop around it, to prevent the very unlikely event of all characters, or too many characters being special characters, and then substring throwing an exception.

private string GetAlphaNumericRandomString(int length)
{
    string randomString = "";
    while (randomString.Length < length)
    {
      //generates a random string, of twice the length specified, to counter the 
      //probability of the while loop having to run a second time
      randomString += Membership.GeneratePassword(length * 2, 0);

      //replace non alphanumeric characters
      randomString = Regex.Replace(randomString, @"[^a-zA-Z0-9]", m => "");
    }
    return randomString.Substring(0, length);
}
King answered 17/4, 2018 at 10:7 Comment(0)
B
0

This is what I use:

public class RandomGenerator
{
    //Guid.NewGuid().ToString().Replace("-", "");
    //System.Web.Security.Membership.GeneratePassword(12, 0);

    private static string AllowChars_Numeric = "0123456789";
    private static string AllowChars_EasyUpper = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static string AllowChars_EasyLower = "0123456789abcdefghijklmnopqrstuvwxyz";
    private static string AllowChars_Upper_Lower = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    private static string AllowedChars_Difficult = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#@$^*()";

    public enum Difficulty
    {
        NUMERIC = 1,
        EASY_LOWER = 2,
        EASY_UPPER = 3,
        UPPER_LOWER = 4, 
        DIFFICULT = 5
    }

    public static string GetRandomString(int length, Difficulty difficulty)
    {
        Random rng = new Random();
        string charBox = AllowedChars_Difficult;

        switch (difficulty)
        {
            case Difficulty.NUMERIC:
                charBox = AllowChars_Numeric;
                break;
            case Difficulty.EASY_LOWER:
                charBox = AllowChars_EasyUpper;
                break;
            case Difficulty.EASY_UPPER:
                charBox = AllowChars_EasyLower;
                break;
            case Difficulty.UPPER_LOWER:
                charBox = AllowChars_Upper_Lower;
                break;
            case Difficulty.DIFFICULT:
            default:
                charBox = AllowedChars_Difficult;
                break;
        }

        char[] chars = new char[length];

        for (int i=0; i< length; i++)
        {
            chars[i] = charBox[rng.Next(0, charBox.Length)];
        }

        return new string(chars);
    }
}
Beefwood answered 10/11, 2022 at 11:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.