Should I use a password pattern like a-zA-Z0-9 and also require at least one of each character class in the password, or simply allow anything inside the password?
What do sites allow the user to use as his/her password? Is there anything else I should consider?
a-ZA-Z0-9 is overly limited. You should let me use any characters, and enforce minimum requirements (i.e. at least 8 characters, at least one letter and one number)
Password Entropy
The test of a good password is not the number of sets of characters represented but Entropy.
Testing for Entropy: The people at Dropbox have put together this fantastic tool called zxcvbn to do just that. I would highly recommend reading their write-up explaining it here.
Brief Explanation: Both character classes (lower case, upper case, digits and special characters) and length are both important because together they raise password entropy (length does this much faster than character classes though) but users then tend toward predictable patterns which lowers entropy.
This may be humour but it helpfully illustrates part of the point:
http://xkcd.com/936/
There should be no limit to what the user should be able to use. Since you would hash the password before you store it anyways (i hope) this will make no difference what the password contain.
If you set requirements, they should be minimum requirements.
Password Regular Expression Pattern
((?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[##$%]).{6,20})
Breakdown
( # Start of group
(?=.*\d) # must contains one digit from 0-9
(?=.*[a-z]) # must contains one lowercase characters
(?=.*[A-Z]) # must contains one uppercase characters
(?=.*[##$%]) # must contains one special symbols in the list "##$%"
. # match anything with previous condition checking
{6,20} # length at least 6 characters and maximum of 20
) # End of group
Related:
Regular Expression for Password
minimum 8 characters, preferable 12
at least one digit, at least one lower case, at least one upper case, at least one symbol (*/%...)
Related
This question already has answers here:
Regex for password must contain at least eight characters, at least one number and both lower and uppercase letters and special characters
(42 answers)
Closed 2 years ago.
So before any one shuts this down, I am referencing an answer and asking a question here.
So the question I have is I want a strong password validation for laravel, something that includes 10 character, numbers, upper lower case, so on and so forth.
I found it: https://stackoverflow.com/a/31549892/1270259
The problem is, this regex looks off:
/^.*(?=.{3,})(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[\d\X])(?=.*[!$#%]).*$/
And since I am not good with regex I thought I would ask how can I fix it such that it validates:
Must be 10 characters long
Must contain upper and lower case
Must contain at least one number
Must contain at least one special character.
I feel like they were close in the answer. When this is run against github actions the error that comes back is preg_match(): Compilation failed: escape sequence is invalid in character class at offset 46.
Any thoughts as too how I can make this work for Laravel 7 to match the above constraints?
Use the principle of contrast:
^
(?=[^a-z]*[a-z]) # ensure one lower case letter
(?=[^A-Z]*[A-Z]) # ensure one upper case letter
(?=\D*\d) # ensure a digit
(?=[^!#?]*[!#?]) # special chars
.{10,} # at least 10 characters long
$
You can extend the special char section, of course.
See a demo on regex101.com.
This question already has an answer here:
Reference - Password Validation
(1 answer)
Closed 5 years ago.
I found a script online and it has a password regex in JavaScript. I still want to use it, but for more security I want to use PHP to validate my password too but I'm useless with regex.
The requirements:
Must be a minimum of 8 characters
Must contain at least 1 number
Must contain at least one uppercase character
Must contain at least one lowercase character
How can I construct a regex string to meet these requirements?
^\S*(?=\S{8,})(?=\S*[a-z])(?=\S*[A-Z])(?=\S*[\d])\S*$
From the fine folks over at Zorched.
^: anchored to beginning of string
\S*: any set of characters
(?=\S{8,}): of at least length 8
(?=\S*[a-z]): containing at least one lowercase letter
(?=\S*[A-Z]): and at least one uppercase letter
(?=\S*[\d]): and at least one number
$: anchored to the end of the string
To include special characters, just add (?=\S*[\W]), which is non-word characters.
I find that doing it in one big regex is a bit of a code maintenance nightmare. Splitting it up is far easier to figure out for someone else looking at your code, and it allows you to give more specific error messages as well.
$uppercase = preg_match('#[A-Z]#', $password);
$lowercase = preg_match('#[a-z]#', $password);
$number = preg_match('#[0-9]#', $password);
if(!$uppercase || !$lowercase || !$number || strlen($password) < 8) {
// tell the user something went wrong
}
One possible regex pattern is:
/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{8,}$/
As in this example.
But you really shouldn't limit passwords!
Admit it. As a developer we have done more to contribute to the failure of our customer's and user's online security because we are too stubborn or lazy to handle passwords properly. Just look at some of the fruit of our labor:
Password must be between 5 and 32 characters in length. Valid characters include letters, numbers, and underscore.
Password must be between 6 and 12 characters in length. Valid characters include letters and numbers.
Password must be a minimum of 8 characters and contain at least one capital letter, a number and a special character such as an underscore or exclamation point.
Then there is this gem. The original requirements were a minimum of 8 characters. Accidentally putting in 7 characters causes an error to appear before the user:
Password Limitation Gone Wrong
Note the tag line. Irony?
I could go on here, but I think you get the point. We have written code to support this nonsense, wrapping our heads around the right regex to account for every case. Agonizing over transmission, hashing and storage. We've talked about this so much the situation has even received proper pop culture status with its memorialization on xkcd.
There is no doubt our intentions were good. After all, users and customers cannot be expected to protect themselves properly. They don't create strong passwords, they use the word 'password' as their password more often than not. They don't heed the warnings, the news stories or the horror exrpressed by friends who have suffered through identity theft. The hacking of large retail chains phases them very little. We, as developers, set out to help our users avoid these pitfalls. I will alledge our attempts fell short and may have even contributed to the problem.
Very likely we've made it worse.
By placing arcane restrictions on passwords we have actually forced our users into a bad way of thinking and therefore made them seek the path of least resistance, simple, hackable passwords. We did this because we were used to restrictions on us. Sysadmins limited us to 8 characters so we projected the limit on to the rest of the world. It is time we stopped and learned how to handle any length of password with any character included. We may want to exclude white spaces from the password, but other than that we shouldn't place any restrictions on passwords.
Then we can encourage good security practices like passphrases or random words. Users, once they discover this, will be blissfully happy they don't have to remember some goofy combination of letters and numbers like f#rtp00p.
I can see you rolling your eyes. It means you have to learn how to properly hash passwords and how to compare entered passwords with the hashes. You'll have to toss some really hard won regex. Heaven forbid you might have to refactor some code! Databases can hold very large hashed passwords and we should take advantage of the capability.
Keep in mind the general security of the data is on me, the developer along with the sysadmin and others. The security of a user's account is on them and I shouldn't do anything to hold them back. Personally I do not care what my users have for their passwords. All I do when users create their passwords is provide a strength meter and some basic guidelines:
"We have found using passphrases or multiple word combinations to be the most secure when it comes to preventing a hacker, who is trying to crack your login information, from being successful."
What should you do?
PHP's built-in functions handle password security perfectly, spaces, special characters and all.. If you're using a PHP version less than 5.5 you can use the password_hash() compatibility pack.
We need to remove the limitations on passwords and free up the users to own their security online. Are you in?
PHP regular expression for strong password validation
The link above looks like the regex you want. You could try something like the code below:
if(preg_match((?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$), $_POST['password']):
echo 'matched';
else:
echo 'not matched';
endif;
This checks for min. 1 number and also min/max chars:
^(?=.*\d)(?!.*\s).{4,8}$
I'm trying to make a check on the password inserted by a user, working on a PHP website.
My check wants to:
at least 8 characters
maximum 20 characters
accept letters, numbers, and common special characters like (dot) # + $ - _ !
Until this point I've been able to figure out the right expression, but now I want to add an other rule, where an user can't write the same sequence of letter more then 1 time.
Let's say that, not considering the repetition of two times of the same letter, if the user write the same string (equal or more than 3 characters) more then once, it should not match.
For example:
abcde not valid - should be at least 8 characters
abcde1234 valid
abcd1abcd1 not valid due to repetition of the string abcd1
More examples (updated):
abababab not valid - the string "ab" is repited 2 times or more
aaaaaaaa not valid - the string aaa is repited more then once
helloworld valid - even if there is the letter "l" repeated two times
Any suggestion?
I don't know is it's possibile to write down a correct RegExp, maybe I'm trying to do something impossibile.
Before leaving the idea, I was curious to check the opinion of someone who know more then me in RegExp.
Thanks in advance
^(?!.*?(.+)\1)([\w#+$!.-]+){8,20}$
seems to work well: http://regex101.com/r/cU9lD0/1
The tricky part is ^(?!.*?(.+)\1) which reads "start of input, when not followed by: something, then some substring, then that substring once again".
That being said, all "password validation" is a quite pointless enterprise, which actually stops people from using really good passwords.
I have a regex that was written for me for passwords:
~^[a-z0-9!##\$%\^&\*\(\)]{8,16}$~i
It's supposed to match strings of alphanumerics and symbols of 8-16 characters. Now I need to remove the min and max length requirement as I need to split the error messages for user friendliness - I tried to just take out the {8,16} portion but then it breaks it. How would I do this? Thanks ahead of time.
I take it you're doing separate checks for too-long or too-short strings, and this regex is only making sure there are no invalid characters. This should do it:
~^[a-z0-9!##$%^&*()]+$~i
+ means one or more, * means zero or more; it probably doesn't matter which one you use.
I got rid of some unnecessary backslashes, too; none of those characters has any special meaning in a character class (inside the square brackets, that is).
I'm using the following regex to validate password complexity:
/^.*(?=.{6,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/
In a nutshell: 2 lowercase, 2 uppercase, 2 numbers, min length is 6 and max length is 12.
It works perfectly, except for the maximum length, when I'm using a minimum length as well.
For example:
/^.*(?=.{6,})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/
This correctly requires a minimum length of 6!
And this:
/^.*(?=.{,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/
Correctly requires a maximum length of 12.
However, when I pair them together as in the first example, it just doesn't work!!
What gives? Thanks!
You want:
/^(?=.{6,12}$)...
What you're doing is saying: find me any sequence of characters that is followed by:
6-12 characters
another sequence of characters that is followed by 2 digits
another sequence of characters that is followed by 2 uppercase letters
another sequence of characters that is followed by 2 lowercase letters
And all that is followed by yet another sequence of characters. That's why the maximum length isn't working because 30 characters followed by 00AAaa and another 30 characters will pass.
Also what you're doing is forcing two numbers together. To be less stringent than that but requiring at least two numbers anywhere in the string:
/^(?=.{6,12}$)(?=(.*?\d){2})(?=(.*?[A-Z]){2})(?=(.*?[a-z]){2})/
Lastly you'll note that I'm using non-greedy expressions (.*?). That will avoid a lot of backtracking and for this kind of validation is what you should generally use. The difference between:
(.*\d){2}
and
(.*?\d){2}
Is that the first will grab all the characters with .* and then look for a digit. It won't find one because it will be at the end of the string so it will backtrack one characters and then look for a digit. If it's not a digit it will keep backtracking until it finds one. After it does it will match that whole expression a second time, which will trigger even more backtracking.
That's what greedy wildcards means.
The second version will pass on zero characters to .*? and look for a digit. If it's not a digit .*? will grab another characters and then look for a digit and so on. Particularly on long search strings this can be orders of magnitude faster. On a short password it almost certainly won't make a difference but it's a good habit to get into of knowing how the regex matcher works and writing the best regex you can.
That being said, this is probably an example of being too clever for your own good. If a password is rejected as not satisfying those conditions, how do you determine which one failed in order to give feedback to the user about what to fix? A programmatic solution is, in practice, probably preferable.