Reputation:
I'm looking to do some pattern matching for passwords, and found a regex example on SO, but when I pass a password through which should be deemed "strong", I am met with the opposite. For example, the string "JlcimYQF+EkHVA*" yields a rating of 1, which means that the string patterns aren't being matched in the regex, but I am unsure why.
Code below:
public class PasswordAdvisor
{
public static PasswordScore CheckStrength(string password)
{
int score = 1;
if (password.Length < 12)
return PasswordScore.TooShort;
if (password.Length >= 16)
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;
}
}
Deceleration:
var passwordStrengthScore = PasswordAdvisor.CheckStrength(@"JlcimYQF+EkH*VA");
Console.WriteLine((int)passwordStrengthScore);
switch (passwordStrengthScore)
{
case PasswordScore.TooShort:
Console.WriteLine("Password is too short");
break;
case PasswordScore.Weak:
Console.WriteLine("Password is very weak");
break;
case PasswordScore.Medium:
Console.WriteLine("OK password");
break;
case PasswordScore.Strong:
Console.WriteLine("Strong password");
break;
case PasswordScore.VeryStrong:
Console.WriteLine("Very strong password");
break;
}
Upvotes: 4
Views: 272
Reputation: 626851
You should remove /
delimiters from all patterns as .NET regexes are defined with string literals, no delimiters are required, and these /
chars are part of the patterns that do not match what you expect.
You should replace @"/.[!,@,#,$,%,^,&,*,?,_,~,-,£,(,)]/"
with @"[!,@#$%^&*?_~£()-]"
to require at least one of these special chars. Note that an unescaped -
inside a character class between literals creates a range, thus it is safer to put it at the end (or escape it). NOTE: I kept the comma inside, but since you used it as an OR operator, probably, you should remove it completely. The OR relationship is the default one between atoms in a positive character class.
In all but Regex.Match(password, @"\d+", RegexOptions.ECMAScript)
statements, you may safely remove RegexOptions.ECMAScript
option that only affects shorthand character class (like \s
, \d
, etc.).
Use
if (Regex.Match(password, @"\d+", RegexOptions.ECMAScript).Success)
score++;
if (Regex.Match(password, @"[a-z]").Success &&
Regex.Match(password, @"[A-Z]").Success)
score++;
if (Regex.Match(password, @"[!,@#$%^&*?_~£()-]").Success) // check if you need a comma here
score++;
Upvotes: 3