-2

I'm not good at regular expressions. I need to do the validate if a password is correct or not.

Conditions:

Your password can be 8-32 characters long and it must include at least two of the following characters:

  1. At least one letter (uppercase or lowercase)
  2. At least one number
  3. At least one special character

The Regex from regex to allow atleast one special character, one uppercase, one lowercase(in any order) requires all three of each and has no upper limit on length, so it appears I need to modify the solution by Tim Pietzcker, which is

^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$

will match any string of at least 8 characters that contains at least one lowercase and one uppercase ASCII character and also at least one character from the set @#$%^&+= (in any order).

dbc
  • 104,963
  • 20
  • 228
  • 340
Manikanta
  • 89
  • 2
  • 14

2 Answers2

0

Regex typically parses strings from left to right - however these (?=xxx) bits called "lookaheads" cause it to validate that part, without including the data into the matched string, nor advancing the "cursor".

It makes the regex look complicated (and may cause performance issues when using large strings), but it does get the job done. Even though I agree with FCin's comment that you don't need regex, a big plus if you ask me is that you can store them in a settings file.

Breaking your example down:

^                      Matches the start of the string
(?=.{8,})              Matches when there are at least 8 characters
(?=.*[a-z])            Matches when there is a lowercase letter anywhere
(?=.*[A-Z])            Matches when there is an uppercase letter anywhere
(?=.*[@#$%^&+=])       Matches when there is one of the indicated characters anywhere
.*                     Matches anything. No lookahead so this advances the "cursor"
$                      Matches the end of the string

You just need to combine the lowercase and uppercase ones:

(?=.*[A-Za-z])

Add the one that matches a number:

(?=.*[0-9])

The "length" rule can actually be done in the last bit without a lookahead:

.{8,32}

Together with the "special character", this would then combine to:

^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}$
C.Evenhuis
  • 25,996
  • 2
  • 58
  • 72
0

Also,

The first case: At least one letter (uppercase or lowercase) and At least one number

((?=.*[A-Z])|(?=.*[a-z]))(?=.*[0-9]).{8,32}

The result: enter image description here

The second case: At least one letter (uppercase or lowercase) and At least one special character

((?=.*[A-Z])|(?=.*[a-z]))(?=.*[@#$%^&+=]).{8,32}

enter image description here

The third case: At least one number and At least one special character

(?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}

enter image description here

Now that the three previous cases have been merged, the pattern will become:

(((?=.*[A-Z])|(?=.*[a-z]))(?=.*[0-9])).{8,32}|((?=.*[A-Z])|(?=.*[a-z]))(?=.*[@#$%^&+=]).{8,32}|(?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}

This is the result you want: enter image description here


Explanation:

The part : (((?=.*[A-Z])|(?=.*[a-z]))(?=.*[0-9])).{8,32}

(?=.*[A-Z])|(?=.*[a-z]) : letters (uppercase or lowercase)

(?=.*[0-9])) : Number

{8,32} 8 to 32 characters


The part : ((?=.*[A-Z])|(?=.*[a-z]))(?=.*[@#$%^&+=]).{8,32}

(?=.*[A-Z])|(?=.*[a-z]) : letters (uppercase or lowercase)

(?=.*[@#$%^&+=]) : special characters

{8,32} 8 to 32 characters


The part : (?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}

(?=.*[0-9])) : Number

(?=.*[@#$%^&+=]) : special characters

{8,32} 8 to 32 characters


This is a simple code to testing the pattern:

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        // Passwords
        String[] passwords = new String[8];

        passwords[0] = "ABCabc123";    //  letters (uppercase or lowercase) and numbers                           : VALID
        passwords[1] = "*+uu*+aa";     //  letters (uppercase or lowercase) and special characters                : VALID
        passwords[2] = "123+*$0*";      //  numbers and special characters                                        : VALID
        passwords[3] = "ABCabc123*$#"; //  letters (uppercase or lowercase) and numbers and special characters    : VALID
        passwords[4] = "ABCDabcd";     //  letters (uppercase and lowercase)                                      : INVALID
        passwords[5] = "abcdefg";      //  letters (lowercase)                                                    : INVALID
        passwords[6] = "ABCDEFGH";     //  letters (uppercase)                                                    : INVALID
        passwords[7] = "123456789";   //  numbers                                                                 : INVALID

        // Password validation  pattern
        var Validation = new Regex(@"((?=.*[A-Z])|(?=.*[a-z]))(?=.*[0-9]).{8,32}|((?=.*[A-Z])|(?=.*[a-z]))(?=.*[@#$%^&+=]).{8,32}|(?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}");

        // Validat the passwords
        for (int i = 0; i < passwords.Length; i++){
            var isValidated = Validation.IsMatch(passwords[i]);
            Console.WriteLine(isValidated);
        }
    }
}

The result:

enter image description here

If you want to validate the password according to the conditions separately, I've defined 3 patterns, compatible with the conditions you want:

1- hasLetterAndNumber

2- hasLetterAndCharacter

3- hasNumberAndCharacter

Passwords will be validated, which correspond to one of the preceding conditions:

using System;
using System.Text.RegularExpressions;

public class Program
{
    public static void Main()
    {
        // Passwords
        String[] passwords = new String[8];

        passwords[0] = "ABCabc123";    //  letters (uppercase or lowercase) and numbers                           : VALID
        passwords[1] = "*+uu*+aa";     //  letters (uppercase or lowercase) and special characters                : VALID
        passwords[2] = "123+*$0*";      //  numbers and special characters                                        : VALID
        passwords[3] = "ABCabc123*$#"; //  letters (uppercase or lowercase) and numbers and special characters    : VALID
        passwords[4] = "ABCDabcd";     //  letters (uppercase and lowercase)                                      : INVALID
        passwords[5] = "abcdefg";      //  letters (lowercase)                                                    : INVALID
        passwords[6] = "ABCDEFGH";     //  letters (uppercase)                                                    : INVALID
        passwords[7] = "123456789";   //  numbers                                                                 : INVALID

        // Password validation  pattern
        var hasLetterAndNumber = new Regex(@"((?=.*[A-Z])|(?=.*[a-z]))(?=.*[0-9]).{8,32}");
        var hasLetterAndCharacter = new Regex(@"((?=.*[A-Z])|(?=.*[a-z]))(?=.*[@#$%^&+=]).{8,32}");
        var hasNumberAndCharacter = new Regex(@"(?=.*[0-9])(?=.*[@#$%^&+=]).{8,32}");

        // Validat the passwords
        for (int i = 0; i < passwords.Length; i++){

            if((hasLetterAndNumber.IsMatch(passwords[i])) || (hasLetterAndCharacter.IsMatch(passwords[i])) || (hasNumberAndCharacter.IsMatch(passwords[i]))){
                Console.WriteLine(passwords[i]);
                Console.WriteLine("\n");
            }
        }
    }
}

enter image description here

Husam Ebish
  • 4,893
  • 2
  • 22
  • 38