Mike Upjohn Mike Upjohn - 7 days ago 5
C# Question

Regex for a Complex Password

I've got this Regex as a data annotation on a password field in a C# .NET MVC project.

[RegularExpression("(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[*+\\/|!\"£$%^&*()#[\\]@~'?><,.=-_]).{6,}", ErrorMessage = "Password must be between 6 and 20 characters and contain one uppercase letter, one lowercase letter, one digit and one special character.")]


I want to make the following passwords invalid:-


  • Testing

  • Testing1

  • TesTinG123



The following would be valid:-


  • Testing1*

  • T&sting123*

  • %F&y5HD$S



I would like a minimum of 6 characters, with at least one uppercase, one lower case, one digit and one special character. I hope the above regex would do it, but it lets Testing12 and Tester12 through as valid passwords.

What can I change in the above to get what I am expecting? I assumed the above requires one uppercase, one lowercase, one numeric and one special character but obviously I am wrong?

Thanks in advance!

Answer

You forgot to escape ] properly (it is advised to even put it at the start of the character class so that in .NET it could be parsed as a literal ] - for the client side validation, it needs to be escaped even there) and remember that a hyphen inside a character class creates a range (e.g. [=-_]), so it must be put at the end/start of the character class or at the end to denote a literal -).

Use

"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\]*+\\/|!\"£$%^&*()#[@~'?><,.=_-]).{6,}$"
                                         ^^                             ^

Or, if you just want to require at least 1 char that is not alphanumeric, use

"^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\W_]).{6,}$"

where [\W_] matches any char but a word char (i.e. [^\p{L}\p{N}_] or - on client side - [^a-zA-Z0-9_]) + _.

The ^ and $ anchors are redundant in the RegularExpressionAttribute pattern, but they won't do any harm.

See the regex demo.