Are password requirements any good?

Mateusz Piatkowski
4 min readAug 6, 2022
Photo by Fly:D on Unsplash

Not long ago I had to implement a simple system for validating user passwords against some business requirements. Their objective was to have more secure passwords in the web platform we are developing and subsequently less probability of data breaches. The idea sounds completely reasonable, but than questions appeared. A lot of questions.

The requirements were following:

  • Password should be at least 12 characters
  • Password should have at most 64 characters
  • Password should contain at least one lowercase and one uppercase letter
  • Password should contain at least one number
  • Password should contain at least one special character

Let me argue with each of this statements one by one.

Password Length

Forcing the minimum length is generally a good idea. It forces the user to think a bit more and not use the password like 1234. But forcing the maximum length? If you are doing things right you probably hash user passwords using something like Argon2. In this case you should not care about the length of the password. I was not sure if the hashing algorithm would be slower on longer passwords, so I did some testing:

Argon2 speed test

I used the code above to see if the algorithm slows down with the input length. The outcome is surprising:

AVG for 10 kB: 0.056545078754425
AVG for 100 kB: 0.05896110534668
AVG for 1000 kB: 0.059655959606171
AVG for 100000 kB: 0.059954657554626

As you can see the algorithm is almost as fast on 10B as on 100kB passwords, so from business perspective I don’t see any reason to limit the password length. There are other security issues that must be addressed in case of large user input like the limit of POST body size, but it’s another story.

Uppercase and Lowercase characters

Sounds reasonable too. We’ll just apply some simple regular expressions: [a-z] and [A-Z] and if there is no match we fail. Well… almost. Firstly keep in mind that the a-z range only contains the Latin characters excluding all letters diacritical marks such as “á”, “ł” or “ó”. Those are lowercase characters. The problem with those is that they are not all together in the UTF-8 table. You can see that, for instance, the polish lowercase letter “ł” is between two uppercase characters “Ł” and “Ń”.

In this case you could start doing things like “uppercasing” and “lowercasing” the password to see if it changes (if it changes on changing to uppercase it means it contains lowercase letters and vice versa). But keep in mind that you have to use functions that actually support this letters (like multibyte string functions in PHP).

Numbers

This one is very easy. The regex to apply is something like [\d] also everybody knows what a number is, so it’s easy to explain to the user what he is missing in his input. However there was a research made on the leaked database of passwords from RockYou that shows that most of the users, in order to fulfill this requirement just adds a number 1 in the end of their password. The rhetorical question is — does it really increase the password security?

Special Characters

This one is probably my favorite. At first we thought that a simple regular expression [\W] which means “not word character” would solve the problem. However, you can see in the documentation that \W is equivalent to [^A-Za-z0-9_]. So it includes all the letters with diacritical marks that we have just treated as lowercase and uppercase letters (“á”, “ł” or “ó”). This way we make the rules ambiguous. We can use one character “ó” and it will count both for lowercase letter and special character!

Second approach was to define the list of characters. We found this arbitrary list of special characters to use in passwords and applied the appropriate Regex. But in this case you must list to the user exactly which characters he must use in his password. What if he wants to use the € sign? Or an emoji
💩? Is that not a special character?

You could probably build a crazy long regular expression that will match all printable characters that are not lowercase or uppercase letters in every possible alphabet. But that sounds like a horrible idea.

Possible Solution

Firstly let me say, that I know, that most of the users will understand “uppercase letter” or “special character” the way the common sense is telling us and create passwords like Bobby2005!. That’s a passwords, it’s probably not the best, especially if your dog’s name is Bobby and you were born in 2005, but it would work. However the password requirements tend to be annoying for users. To complicated rules make them forget their passwords, they get angry during the registration process. And most important, they have to read the rules, understand them, and make an effort to apply them. The simpler solution is measuring the password strength but not checking it’s content. That also forces the user to invent a strong password but does not give the set of rules that he must read and apply.

A possible solution is the library developed by Dropbox called zxcvbn. It evaluates the passwords and returns the score (as well as other information). The lower the score the less secure the password is. Probably there are other tools doing similar things, I just gave this as an example. It’s an open source project, you can check what exactly it is doing in their Github page and analyze the algorithm if you wish. It will definitely be the approach I will use in my future projects. It has one disadvantage — you depend on an external library and you give the security of your app in its hands. But hey, are you not doing it all the time when using OpenSSL or Paragonie?

--

--

Mateusz Piatkowski

Senior Software Engineer (Java, PHP, Node, APIs), 100% FOSS. Living between Poland and Spain. 🇵🇱🇬🇧🇪🇸