-2

I have a password rule to be follow, required the password must contain 2 alphabet (upper or lowercase) & 6 numbers, and the whole length is expected to equal 8 symbols.

Here's the samples that should pass:

a123456b
1a2b3456
aa123456
123ab456

And the samples that should fail:

1abcdefg2
a1234567b
abcdefgh
12345678

And I need a regular expression to fit this rule.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
Leo.W
  • 299
  • 1
  • 7
  • 21
  • I need a regular expression to validate the password – Leo.W Sep 26 '16 at 03:11
  • 2
    why`a1234567b` is under bad password sample. it contains 2 letter and 6 numbers – Deepak Sharma Sep 26 '16 at 03:23
  • It's generally bad for security to enforce rules like this. It often forces people to choose a new password _which they then have to write down to remember_. It's better to show a "strength" score and let the user choose what they want. – Enigmativity Sep 26 '16 at 03:24
  • @GiladNaaman yes, i exactly want 2 letters and 6 numbers – Leo.W Sep 26 '16 at 03:51
  • @Enigmativity sorry, this is a special case, the password rule is from vendor and we have to follow – Leo.W Sep 26 '16 at 03:53
  • I'd rather you specify *in the question* that you do not really need the code based answer, only a regex, and really, you could "cook" something by yourself, see http://stackoverflow.com/questions/19605150/regex-for-password-must-be-contain-at-least-8-characters-least-1-number-and-bot. (I found it on google using `password regex at least 2 letters and 6 digits` search). – Wiktor Stribiżew Sep 26 '16 at 06:21
  • Another thing: by tagging the question with `C#`, people will think you accept the C# code based answer. Replace c# with .net tag. – Wiktor Stribiżew Sep 26 '16 at 08:29
  • [`^(?=.{8}$)(?:\d*[a-z]){2}\d*$`](https://regex101.com/r/aU7yV9/1) and use `(?i)` if case insensitivity is necessary. – Wiktor Stribiżew Sep 26 '16 at 09:46

3 Answers3

3

Edit: TL;DR: Regex are not the tool for the job, and the job doesn't need to be done.

Regex is not the solution to the problem, and AFAIK it is impossible to use it to solve your problem. (But don't take my word for it, I bet someone wrote some funky extension to an esoteric Regex engine that does just this)

If it is possible, the solution will be unreadable. It is better to just check the result of Count.

Something along the lines of (haven't actually compiled this):

bool IsPasswordValid(string pw)
{
    return pw.Length == 8 && 
            pw.Count(char.IsNumber) == 6 &&
            pw.Count(char.IsLetter) == 2;
}

Notes:

Regular Expressions are (is?) a tool that is used to check a string against a pattern. The simpler the pattern, the easier it is to write a regex for it. Since you want your password to have 2-chars of a set anywhere in the string, and 6 character of another set also anywhere in the string, it is very hard (or even impossible) to create such a pattern.

If your problem was "I want the password to start with 2 digits and end with 6 letters", the answer would've been trivial, but since the digits and letters can be separate and anywhere in the string, it is not as trivial.

Also, most of the time, enforcing password patterns does not increase security. If you have to do anything, enforce a sane minimum length ans stop there.

Gilad Naaman
  • 6,390
  • 15
  • 52
  • 82
1

A regex approach can be multiple, here are 2: 1) require the legnth of 8 chars with a lookahead like (?=.{8}$) and use a consuming pattern allowing zero or more digits before a letter twice, and then match zero or more letters, 2) match 8 letters or digits, but use a lookahead restriction to match 2 alphabets.

Example 1:

^(?=.{8}$)(?:\d*[a-z]){2}\d*$

Details:

  • ^ - start of string
  • (?=.{8}$) - the length should be 8 non-newline symbols only
  • (?:\d*[a-z]){2} - 2 sequences of 0+ digits followed with 1 letter
  • \d* - 0+ digits
  • $ - end of string.

See the regex demo

Example 2:

^(?=(?:\d*[a-z]){2}\d*$)[\da-z]{8}$

Details:

  • ^ - start of string
  • (?=(?:\d*[a-z]){2}\d*$) - there must be 2 sequences of 0+ digits and a letter followed with 0+ digits up to the end of string
  • [\da-z]{8} - 8 digits or letters
  • $ - end of string.

See the regex demo 2

Note that to enable case insensitive mode, you can prepend the pattern with (?i) / RegexOptions.IgnoreCase flag, and if you need to only match ASCII digits, use RegexOptions.ECMAScript or replace \d with [0-9].

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

Actually,there is a nice way to do it:

    public static bool CheckPasswordRule(string password)
    {
        var isRuleAdhered = (Regex.Matches(password, "\\d").Count == 6 && Regex.Matches(password, "[a-z]").Count == 2);

        return isRuleAdhered;
    }

If you still want to not have 6 digits one after another you can modify the code to:

    public static bool CheckPasswordRule(string password)
    {
        var isRuleAdhered= false;
        isRuleAdhered = Regex.Matches(password, "\\d").Count == 6 && Regex.Matches(password, "[a-z]").Count == 2 && !Regex.IsMatch(password, "\\d{6}");
        return isRuleAdhered;
    }
αNerd
  • 528
  • 1
  • 6
  • 11
  • Yes, there's many way to meet the requirement, the reason why i need the Regex is trying to provide the flexible in case the rule is changed in some day – Leo.W Sep 26 '16 at 05:19
  • If you want flexible regex for the count of digits and letters you can use variables and replace 6 and 2 accordingly. For other rules you will need to change the regex or add another regex. – αNerd Sep 26 '16 at 05:23