[c#] Regular Expression for password validation

I currently use this regular expression to check if a string conforms to a few conditions.

The conditions are string must be between 8 and 15 characters long. string must contain at least one number. string must contain at least one uppercase letter. string must contain at least one lowercase letter.

(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,15})$

It works for the most part, but it does not allow special character. Any help modifying this regex to allow special character is much appreciated.

This question is related to c# .net regex

The answer is


I would check them one-by-one; i.e. look for a number \d+, then if that fails you can tell the user they need to add a digit. This avoids returning an "Invalid" error without hinting to the user whats wrong with it.


Is a regular expression an easier/better way to enforce a simple constraint than the more obvious way?

static bool ValidatePassword( string password )
{
  const int MIN_LENGTH =  8 ;
  const int MAX_LENGTH = 15 ;

  if ( password == null ) throw new ArgumentNullException() ;

  bool meetsLengthRequirements = password.Length >= MIN_LENGTH && password.Length <= MAX_LENGTH ;
  bool hasUpperCaseLetter      = false ;
  bool hasLowerCaseLetter      = false ;
  bool hasDecimalDigit         = false ;

  if ( meetsLengthRequirements )
  {
    foreach (char c in password )
    {
      if      ( char.IsUpper(c) ) hasUpperCaseLetter = true ;
      else if ( char.IsLower(c) ) hasLowerCaseLetter = true ;
      else if ( char.IsDigit(c) ) hasDecimalDigit    = true ;
    }
  }

  bool isValid = meetsLengthRequirements
              && hasUpperCaseLetter
              && hasLowerCaseLetter
              && hasDecimalDigit
              ;
  return isValid ;

}

Which do you think that maintenance programmer 3 years from now who needs to modify the constraint will have an easier time understanding?


Try this ( also corrected check for upper case and lower case, it had a bug since you grouped them as [a-zA-Z] it only looks for atleast one lower or upper. So separated them out ):

(?!^[0-9]*$)(?!^[a-z]*$)(?!^[A-Z]*$)^(.{8,15})$

Update: I found that the regex doesn't really work as expected and this is not how it is supposed to be written too!

Try something like this:

(?=^.{8,15}$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?!.*\s).*$

(Between 8 and 15 inclusive, contains atleast one digit, atleast one upper case and atleast one lower case and no whitespace.)

And I think this is easier to understand as well.


You may try this method:

    private bool ValidatePassword(string password, out string ErrorMessage)
        {
            var input = password;
            ErrorMessage = string.Empty;

            if (string.IsNullOrWhiteSpace(input))
            {
                throw new Exception("Password should not be empty");
            }

            var hasNumber = new Regex(@"[0-9]+");
            var hasUpperChar = new Regex(@"[A-Z]+");
            var hasMiniMaxChars = new Regex(@".{8,15}");
            var hasLowerChar = new Regex(@"[a-z]+");
            var hasSymbols = new Regex(@"[!@#$%^&*()_+=\[{\]};:<>|./?,-]");

            if (!hasLowerChar.IsMatch(input))
            {
                ErrorMessage = "Password should contain at least one lower case letter.";
                return false;
            }
            else if (!hasUpperChar.IsMatch(input))
            {
                ErrorMessage = "Password should contain at least one upper case letter.";
                return false;
            }
            else if (!hasMiniMaxChars.IsMatch(input))
            {
                ErrorMessage = "Password should not be lesser than 8 or greater than 15 characters.";
                return false;
            }
            else if (!hasNumber.IsMatch(input))
            {
                ErrorMessage = "Password should contain at least one numeric value.";
                return false;
            }

            else if (!hasSymbols.IsMatch(input))
            {
                ErrorMessage = "Password should contain at least one special case character.";
                return false;
            }
            else
            {
                return true;
            }
        }

Thanks Nicholas Carey. I was going to use regex first but what you wrote changed my mind. It is so much easier to maintain this way.

//You can set these from your custom service methods
int minLen = 8;
int minDigit 2;
int minSpChar 2;

Boolean ErrorFlag = false;
//Check for password length
if (model.NewPassword.Length < minLen)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must be at least " + minLen + " characters long.");
}

//Check for Digits and Special Characters
int digitCount = 0;
int splCharCount = 0;
foreach (char c in model.NewPassword)
{
    if (char.IsDigit(c)) digitCount++;
    if (Regex.IsMatch(c.ToString(), @"[!#$%&'()*+,-.:;<=>?@[\\\]{}^_`|~]")) splCharCount++;
}

if (digitCount < minDigit)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must have at least " + minDigit + " digit(s).");
}
if (splCharCount < minSpChar)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must have at least " + minSpChar + " special character(s).");
}

if (ErrorFlag)
    return View(model);

Pattern satisfy, these below criteria

  1. Password Length 8 and Maximum 15 character
  2. Require Unique Chars
  3. Require Digit
  4. Require Lower Case
  5. Require Upper Case
^(?!.*([A-Za-z0-9]))(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,15}$

Update to Justin answer above. if you want to use it using Data Annotation in MVC you can do as follow

[RegularExpression(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,15}$", ErrorMessage = "Password must be between 6 and 20 characters and contain one uppercase letter, one lowercase letter, one digit and one special character.")]

Long, and could maybe be shortened. Supports special characters ?"-_.

\A(?=[-\?\"_a-zA-Z0-9]*?[A-Z])(?=[-\?\"_a-zA-Z0-9]*?[a-z])(?=[-\?\"_a-zA-Z0-9]*?[0-9])[-\?\"_a-zA-Z0-9]{8,15}\z

Examples related to c#

How can I convert this one line of ActionScript to C#? Microsoft Advertising SDK doesn't deliverer ads How to use a global array in C#? How to correctly write async method? C# - insert values from file into two arrays Uploading into folder in FTP? Are these methods thread safe? dotnet ef not found in .NET Core 3 HTTP Error 500.30 - ANCM In-Process Start Failure Best way to "push" into C# array

Examples related to .net

You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to use Bootstrap 4 in ASP.NET Core No authenticationScheme was specified, and there was no DefaultChallengeScheme found with default authentification and custom authorization .net Core 2.0 - Package was restored using .NetFramework 4.6.1 instead of target framework .netCore 2.0. The package may not be fully compatible Update .NET web service to use TLS 1.2 EF Core add-migration Build Failed What is the difference between .NET Core and .NET Standard Class Library project types? Visual Studio 2017 - Could not load file or assembly 'System.Runtime, Version=4.1.0.0' or one of its dependencies Nuget connection attempt failed "Unable to load the service index for source" Token based authentication in Web API without any user interface

Examples related to regex

Why my regexp for hyphenated words doesn't work? grep's at sign caught as whitespace Preg_match backtrack error regex match any single character (one character only) re.sub erroring with "Expected string or bytes-like object" Only numbers. Input number in React Visual Studio Code Search and Replace with Regular Expressions Strip / trim all strings of a dataframe return string with first match Regex How to capture multiple repeated groups?