locked
Password strength: Exactly 8 characters but must contains at least 2 digits

    Question

  • Hi

     

    I need a password strength as follows:

    • Contains exactly 8 characters
    • Must have at least 2 digits in there

     

    E.g.

    • qwe3rt6y
    • qwe456t6
    • 33rr5ggg

     

    I did try the following but it fails:

     

    (?=.{8})(?=(.*\d){2,})

     

     

    I don't know enough about regular expressions so any help is appreciated

     

     

    Kind regards

     

    Mark Eaton

     

     

    Monday, March 03, 2008 1:41 AM

All replies

  • This worked on your test strings. It also failed (correctly) on the following

    "r5ggg"  - because it was less than 8 characters

    "33rr5gggab" - more than eight characters

    "abrr5ggg - only one digit

     

    The (\w{8}) captures the password. The rest makes sure it has at least two digits and that the password is a stand-alone token.

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

    Ed McElroy

    Monday, March 03, 2008 4:05 PM
  • Hi Ed

     

    Thanks for the quick reply.

     

    I tried what you suggested but I got an error saying that there was a syntax error in the regular expression.

     

    I copied + pasted your example so it looked like below:

     

    regxPassword.ValidationExpression = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

    Was there something I missed?

     

     

    Kind regards

     

    Mark Eaton

     

    Tuesday, March 04, 2008 10:40 PM
  • Hi Mark:

     

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

    string TestStr_1 = "qwe456t6";

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

    string TestStr_5 = "33rr5gggabc";

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

    int MatchIndex = 0;

    foreach (Match m in MatchCol)

    {

    Console.WriteLine("Match index {0}", MatchIndex++);

    Console.WriteLine(m.ToString());

    GroupCollection GroupCol = m.Groups;

    for (int i = 0; i < GroupCol.Count; ++i)

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

    }

     

     

     

    Ed McElroy

    Wednesday, March 05, 2008 12:09 AM
  • There is one small problem with the expression above. It will allow you to exceed 8 characters as long as you separate individual 8 character strings with spaces. For example, the following also works with this expression:

     

    ddd7dd4s ddd7dd4s

     

    Not sure how to get around that. Anybody have a suggestion?

     

    Thanks,

    Tom

    Friday, May 09, 2008 7:35 PM
  • Using anchors:

    Code Snippet

    bool foundMatch = Regex.IsMatch(input, @"\A(?=.*?\d.*\d)\w{8}\z");


    Friday, May 09, 2008 8:49 PM
  • Hi Mark:

     

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

     

    string TestStr_1 = "qwe456t6";

     

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

     

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

     

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

     

    string TestStr_5 = "33rr5gggabc";

     

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

     

    int MatchIndex = 0;

     

    foreach (Match m in MatchCol)

    {

     

    Console.WriteLine("Match index {0}", MatchIndex++);

     

    Console.WriteLine(m.ToString());

     

    GroupCollection GroupCol = m.Groups;

     

    for (int i = 0; i < GroupCol.Count; ++i)

     

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

    }

     

     

     

     

    Ed McElroy

    Sunday, July 19, 2009 2:57 PM
  •  

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

     

    string TestStr_1 = "qwe456t6";

     

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

     

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

     

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

     

    string TestStr_5 = "33rr5gggabc";

     

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

     

    int MatchIndex = 0;

     

    foreach (Match m in MatchCol)

    {

     

    Console.WriteLine("Match index {0}", MatchIndex++);

     

    Console.WriteLine(m.ToString());

     

    GroupCollection GroupCol = m.Groups;

     

    for (int i = 0; i < GroupCol.Count; ++i)

     

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

    }

     

     

     

     

    Ed McElroy

    Sunday, July 19, 2009 2:59 PM
  • Hi Mark:

     

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

     

     

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

     

     

    string TestStr_1 = "qwe456t6";

     

     

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

     

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

     

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

     

    string TestStr_5 = "33rr5gggabc";

     

     

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

     

     

    int MatchIndex = 0;

     

     

    foreach (Match m in MatchCol)

     

    Console.WriteLine("Match index {0}", MatchIndex++);

     

     

    Console.WriteLine(m.ToString());

     

     

    GroupCollection GroupCol = m.Groups;

     

     

    for (int i = 0; i < GroupCol.Count; ++i)

     

     

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

     

    }

     

    {

     

     

     

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

     

     

    string TestStr_1 = "qwe456t6";

     

     

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

     

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

     

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

     

    string TestStr_5 = "33rr5gggabc";

     

     

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

     

     

    int MatchIndex = 0;

     

     

    foreach (Match m in MatchCol)

     

    Console.WriteLine("Match index {0}", MatchIndex++);

     

     

    Console.WriteLine(m.ToString());

     

     

    GroupCollection GroupCol = m.Groups;

     

     

    for (int i = 0; i < GroupCol.Count; ++i)

     

     

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

     

    }

    {

     

    Sunday, July 19, 2009 3:01 PM
  • Already Voted
    Using anchors:

    Code Snippet

    bool foundMatch = Regex.IsMatch(input, @"\A(?=.*?\d.*\d)\w{8}\z");

    Sunday, July 19, 2009 3:02 PM

  • Using anchors:

    Code Snippet

    bool foundMatch = Regex.IsMatch(input, @"\A(?=.*?\d.*\d)\w{8}\z");


    Sunday, July 19, 2009 3:05 PM
  • There is one small problem with the expression above. It will allow you to exceed 8 characters as long as you separate individual 8 character strings with spaces. For example, the following also works with this expression:

     

    ddd7dd4s ddd7dd4s

     

    Not sure how to get around that. Anybody have a suggestion?

     

    Thanks,

    Tom

    Sunday, July 19, 2009 3:05 PM
  • Hi Mark:

     

    I just ran the code again and it worked. The pattern you used seems identical. Are you using it in C#? If you're using it in Visual Basic, the @ sign will create problems. You can just drop the @ sign for VB (of course, I don't know if you're using it in VB, I'm just considering that as a possibility).

     

    Here is the C# code I used for the tests. Of course, I manually edited the Regex.Matches and ran the code for each of the test strings. Give it a try and let me know your results.

     

     

    Code Snippet

     

    string TestStr = "qwe3rt6y";

     

    string TestStr_1 = "qwe456t6";

     

    string TestStr_2 = "33rr5ggg";

    // This should fail because it doesn't have at least

    // two digits.

     

    string TestStr_3 = "abrr5ggg";

    // This should fail because it has less than 8 characters.

     

    string TestStr_4 = "r5ggg";

    // This should fail because it has more than 8 characters

     

    string TestStr_5 = "33rr5gggabc";

     

     

    string PatternStr = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

    MatchCollection MatchCol = Regex.Matches(TestStr, PatternStr);

     

    int MatchIndex = 0;

     

    foreach (Match m in MatchCol)

    {

     

    Console.WriteLine("Match index {0}", MatchIndex++);

     

    Console.WriteLine(m.ToString());

     

    GroupCollection GroupCol = m.Groups;

     

    for (int i = 0; i < GroupCol.Count; ++i)

     

    Console.WriteLine("Group {0}:\n{1}", i, GroupCol[i].ToString());

    }

     

     

     

     

    Ed McElroy

    Sunday, July 19, 2009 3:07 PM
  • Hi

     

    I need a password strength as follows:

    • Contains exactly 8 characters
    • Must have at least 2 digits in there

     

    E.g.

    • qwe3rt6y
    • qwe456t6
    • 33rr5ggg

     

    I did try the following but it fails:

     

    (?=.{8})(?=(.*\d){2,})

     

     

    I don't know enough about regular expressions so any help is appreciated

     

     

    Kind regards

     

    Mark Eaton

     

    Hi Ed

     

    Thanks for the quick reply.

     

    I tried what you suggested but I got an error saying that there was a syntax error in the regular expression.

     

    I copied + pasted your example so it looked like below:

     

    regxPassword.ValidationExpression = @"(?:^|\s+)(\w{8})(?<=(.*\d.*\d.*))(?:\s+|$)";

     

     

    Was there something I missed?

     

     

    Kind regards

     

    Mark Eaton

     

    Sunday, July 19, 2009 3:18 PM
  • (c#)
    string pattern = @"^(?=.*\d.*\d.*$).{8}$";

    This pattern works in ASP.Net's RegularExpressionValidator and other areas as well.

    This pattern allows any character including spaces and limits to exactly 8 characters, per your specification.  To eliminate spaces, or any other character, insert a negative look-head like (?!.*[\s].*$) before the .{8}.

    Ed's use of .*\d.*\d.* is correct when you are looking for at least 2 digits that are not necessarily grouped together, there are ways to further generalize to N digits.  Don't fall to the temptation to use \d{2,} as that would then require they be grouped together.

    There are many posts on this forum discussing Passwords and Usernames and regular expressions used to enforce them, try searching the forum for "password" and for "username".
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Monday, July 20, 2009 12:01 PM
  • Note to all that this original question was asked over a year ago.
    John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
    Monday, July 20, 2009 6:00 PM
  • John,  I missed that.  Thanks
    Les Potter, Xalnix Corporation, Yet Another C# Blog
    Wednesday, July 22, 2009 11:30 AM