26

Possible Duplicate:
Strong password regex
Need RegEx for password strength?

I was just wondering what the best way to search a string for certain criteria (password strength to be specific) could be accomplished.

So far I have a simple:

if(password.Length <= 7)
    {
        errorMessage = "Your password must be at least 8 characters.";
    }

I would like to be able to check for capital letters, but I am not sure what the method or procedure is. I have tried Googling, searching the website: http://msdn.microsoft.com, and searching the index of my C# book (C# Programming 3E, by Barbara Doyle), but I can't seem to find any.

I know I could try this...:

foreach(char c in password)
    {
        if(c!='A' || c!='B' || c!='C' || c!='D' ..... || c!='Z')
        {
            errorMessage = "Your password must contain at least one capital letter";
        }
    }

...But that would be extremely sloppy, and would have to be doubled to check for at least one lowercase letter. I am sure there is a better way to do this, or at least shorthand for the method I have shown above.

Also, I may decide to check the password for special characters (seems easier to do in the example above than with upper and lower case letters, so I may just use that for special characters, should I decide to make them necessary). If there is an easy (or proper) way to do that, I would love to have that knowledge, as well.

Anyway, thank you so much for any help anyone can give.

Community
  • 1
  • 1
VoidKing
  • 6,282
  • 9
  • 49
  • 81
  • 5
    This isn't an answer, but be sure you understand http://xkcd.com/936/ and http://xkcd.com/792/ And I also recommend reading http://www.codinghorror.com/blog/2010/12/the-dirty-truth-about-web-passwords.html and searching Jeff's site for other related articles. Then look at Regular Expressions for verifying the appropriate length/complexity. – David Oct 15 '12 at 16:29
  • Instead of a series of `if...then` clauses, you'd probably want to run the password through a regular expression. Take a look at this [SO answer](http://stackoverflow.com/questions/3131025/strong-password-regex). I think it provides the Regular Expression that will help you. – David Hoerster Oct 15 '12 at 16:30
  • @DarinDimitrov Hey, thanks for that, I didn't see that link, because I didn't know to search for regex (although, I guess it's kind of obvious). My apologies, and thnx for the link! – VoidKing Oct 15 '12 at 16:42
  • I very strongly disagree with the decision to close this question of as a duplicate by referencing only questions asking about regular expressions. The OP did not explicitly ask for a regex answer and some people may not find the use of regex to be the "best" answer since not everyone can easily understand regular expressions. – Aerik Feb 14 '19 at 20:40

1 Answers1

81

I can't take the credit, as I stole this from here

using System.Text;
using System.Text.RegularExpressions;

  public enum PasswordScore
  {
    Blank = 0,
    VeryWeak = 1,
    Weak = 2,
    Medium = 3,
    Strong = 4,
    VeryStrong = 5
  }

  public class PasswordAdvisor
  {
    public static PasswordScore CheckStrength(string password)
    {
      int score = 0;

      if (password.Length < 1)
        return PasswordScore.Blank;
      if (password.Length < 4)
        return PasswordScore.VeryWeak;

      if (password.Length >= 8)
        score++;
      if (password.Length >= 12)
        score++;
      if (Regex.Match(password, @"/\d+/", RegexOptions.ECMAScript).Success)
        score++;
      if (Regex.Match(password, @"/[a-z]/", RegexOptions.ECMAScript).Success &&
        Regex.Match(password, @"/[A-Z]/", RegexOptions.ECMAScript).Success)
        score++;
      if (Regex.Match(password, @"/.[!,@,#,$,%,^,&,*,?,_,~,-,£,(,)]/", RegexOptions.ECMAScript).Success)
        score++;

      return (PasswordScore)score;
    }
  }

Note the use of regex for checking for upper case characters. This appears to be a decent approach, as it checks length, use of upper and lower case characters, numeric digits and special characters.

** Update **

I know the question is now closed, but I can add more explanation for VoidKing to understand some of the concepts.

A PasswordScore is returned from the CheckStrength method, which can be used as the condition for what to do next in your code.

Here's an untested demo of how the above code could be used:

String password = "MyDummy_Password"; // Substitute with the user input string
PasswordScore passwordStrengthScore = PasswordAdvisor.CheckStrength(password);

switch (passwordStrengthScore) {
    case PasswordScore.Blank:
    case PasswordScore.VeryWeak:
    case PasswordScore.Weak:
            // Show an error message to the user
            break;
    case PasswordScore.Medium:
    case PasswordScore.Strong:
    case PasswordScore.VeryStrong:
           // Password deemed strong enough, allow user to be added to database etc
           break;
}

Enums are used in this case as a means of classifying the strength of the password into human-readable groups. Keeps the code clean, and makes it obvious what is going on in the code.

Regarding the use of Regex's, if you're unfamiliar with the concept of them and how and when to use them, I suggest doing some research as these can be useful in many different scenarios for checking for patterns in strings. Perhaps start here.

Tieme
  • 62,602
  • 20
  • 102
  • 156
Steve Kennaird
  • 1,604
  • 13
  • 21
  • Dude, you deserve some rep, just for how useful this is overall... Until now, I had no idea how they rated passwords on that scale... Thank you! – VoidKing Oct 15 '12 at 16:32
  • How does this Regex work exactly? I'd like to be able to make my own. Am I right in assuming that it checks each character (and succeeding characters if the previous is a match) for matches within the regex string provided? (forgive me if I am not using regex correctly, grammatically speaking) – VoidKing Oct 15 '12 at 16:34
  • Well, I was trying this, but I just don't know enough about this procedure. I just started pathing to (or using or whatever its called) external .cs files, and I can do that, but I can't seem to work with any of the data that this class is supposed to supply. It's never enough that I have code, I must also understand it in order to implement it into my applications, and I simply put, do not, here. What is ECMAScript? why enum? what kind of data is returned? (I found out I can't cast it into anything useable). Anyway, thanks for trying to help. – VoidKing Oct 15 '12 at 19:04
  • I've updated the answer to help you further. Hope you find it useful. – Steve Kennaird Oct 16 '12 at 07:45
  • I like it, although I would start the score at 0 to enforce even stronger passwords. As it is now 12345678 would be scored as medium strength, which I really don't agree with. :-) – Nikolaj Dam Larsen Jul 17 '14 at 15:38
  • 3
    The password as `Password@123` will produce `PasswordScore` as `6` which is not defined in `enum`. So the score must start with 0 to make it more reliable function. – Sumit Gupta Aug 06 '14 at 11:49
  • 3
    I had to take out the trailing/leading "/"s to get this to work. – Paul Knopf Feb 04 '15 at 17:45
  • While this is good, it is essentially saying +1 for any of the following( length > 8, length > 12, has a lowercase alphabetical character, has an uppercase alphabetical character, has a digit, has a special character.) Because most of the logic is in regexes, it would be easily extendable to javascript. The only problem is that it doesn't check common words / consecutives etc. Not to say it's not a good solution, it just needs to be taken with a grain of... salt. – user420667 Jun 25 '16 at 03:36
  • Wouldn't `String.IsNullOrEmpty(password)`make more sense than `password.Length < 1`? – Deantwo May 02 '17 at 08:48
  • 1
    @SumitGupta In fact there is a missing `enum` value, score must start at `1` otherwise `password.Length < 4` and `password.Length >= 8`will both return a value of `PasswordScore.VeryWeak`. I added value `PasswordScore.TooShort = 1` and returned this if `password.Length < 4`. All other `enum` values must be incremented by one. I edited the answer with my fixes – JPelletier Sep 08 '17 at 20:07
  • 1
    I "tried" to edit the answer with my fixes, but it seems that it was rejected :( if you copy/paste the code please read my above comment – JPelletier Sep 11 '17 at 12:22
  • I'd add + and =. – Garr Godfrey Oct 24 '20 at 00:02
  • 1
    @JPelletier I'm not sure >=8 being veryweak is a problem, but there's definitely a problem with passwords length 5,6 and 7 returning "Blank" (if they have no other qualities) – Garr Godfrey Oct 24 '20 at 00:06