The Plain Simple Password Page Not So Simple Anymore

The requirements for the management of passwords have become far more complex over the past few years in response to the increasing sophistication of security breaches. Nowadays, you need to provide a range of features such as hashing, routine change of passwords, preventiion of repeat passwords, email confirmation, auto-generation of random passwords and password quality checks. Dino Esposito explains.

Edited: 26th May 2016

Admittedly the topic of this article may not sound particularly enticing at first. It doesn’t refer to any new cool framework or a technology I’d want to advertise; it doesn’t even refer to any buzzwords in vogue these days. It could have been an extremely timely article if written some ten years ago to welcome the ASP.NET membership provider and user-management built-in ASP.NET server controls. But in the middle of 2016, with a new significant redesign of the ASP.NET platform approaching, what kind of value can an article about changing the login password provide? Hopefully, I’ll give a satisfactory answer to that question in the article

This article is about passwords and how you let users change them and what you should do to guarantee appropriate levels of privacy. It also focuses on a few dos and don’ts of password change pages.

Hash the Password

The privacy of data is a hot topic, and data leaks go immediately into the primetime news. Hence, regardless of the size of your application, if you’re using a login form then passwords must be hashed and ideally salted. Storing passwords as hash strings is doubly beneficial: it still allows you to check credentials effectively and guarantees that, in case the database is compromised, no realistic use can be made of any hashed passwords.

Password hashing can easily become a standard programming technique that is as easy to implement as storing password as plain text. You start by adding the following interface definition to your infrastructure class library:

Next, you create a default hasher class. The code below shows a hashing class that does nothing, but it’s the perfect mock to extend with the hashing algorithm you like most.

As far as a realistic body for the  HashInternal function, you might want to look at the Rfc2898DeriveBytes class in the .NET Framework.
(See http://msdn.microsoft.com/en-us/library/system.security.cryptography.rfc2898derivebytes.aspx).

 To make hashing more effective, you might want to use a random string known as the salt value. A salt value is commonly an alphanumeric string of any length-usually the longer the better. The iteration count parameter indicates the number of times you want the hashing algorithm to iterate to make the final hash harder and harder to crack.

Ideally, you create the salt as a random string for each and every user, and store it in the same database table as the credentials. The salt is recommended because its randomness makes brute-force attacks harder and, more importantly, it significantly invalidates the use of rainbow tables-a fancy name for precomputed tables of hashed passwords that hackers may sometimes use.  (See https://en.wikipedia.org/wiki/Rainbow_table.) To generate a strong salt value, consider using the RNGCryptoServiceProvider class. Note, however, that the Rfc2898DeriveBytes class also offer a constructor that automatically generates a salt string of the desired length.

In addition, or even as an alternative to salt values, you can use pepper values. A pepper value is equally a randomly-generated alphanumeric string that is common to all users and stored outside the database, typically in a configuration file. Unlike the salt value, the pepper is kept hidden and distinct from the salt so that knowing one doesn’t lead to know the other. The way you combine salt and pepper values is up to you: the simplest trick is just concatenating clear password, salt and pepper and then calculate the resulting hash.

Ensure a Minimal Length

As obvious as it may sound, the longer the password, the better it is. In addition, the more varied the set of characters it is based on the better. Using lowercase and uppercase letters, numbers and punctuation symbols simply increases the number of permutations a brute force attack must deal with. It is one thing to calculate all the possible permutations of, say, 8 letters in an alphabet of 26, but quite another to go through all permutations of size 12 in an alphabet of 60. The cost of a brute force attack grows exponentially with the range of characters, increasing your security level.

Both the ASP.NET Identity and classic ASP.NET Membership API provide support for the minimum length of a password and don’t accept any that is not long enough. If you’re using any of those membership and authentication frameworks, you’re encouraged to use the feature. If you’re creating your own simple framework, you should definitely avoid accepting any password shorter than a configured length.

In a web application based on logins, you probably have some register form where users enter their name and choose a password. This is the first place where you can apply the rule with an immediate JavaScript check on the password length. Then you can reinforce the same checks on the server side. Needless to say, in case of multitenant applications, the minimum length of the password must be configurable.

Let Users Know How Good is Their Password

If you opted for enforcing a minimum length, then you should also give immediate feedback to users about that as they’re typing the password in the register form. You should do the same also in any forms that you may have for users to change the password once registered. There are plenty of JavaScript libraries and jQuery plugins that help to meter the goodness of a password as it is being typed. Here’s an example:

The HTML input field is bound to a piece of JavaScript code that fires whenever the user types in.

The change-password button is disabled if the password is too short and re-enabled when the password reaches the minimum length. As it is typed, some JavaScript code calculates a score for the text in the input fields and changes the CSS class of the text that indicates how good it is. (See the figure.)

2421-da7b263f-8ace-48dc-b88c-ac2d678cb1c

The algorithm that you use to calculate the score of the password is completely up to you. Common tasks that you might want it to perform include counting distinct letters in the password, assigning a score that proportionally decreased for each repetition of the letter in the password. In addition, add a bonus if lowercase and uppercase are used and if numbers and punctuation symbols are used. The final score is then evaluated against known constants to determine a vote such as Poor, Good, Strong and so on. It’s purely a client-side feature with no impact on server code, but provides timely feedback and possibly encourages users to use more sophisticated passwords.

Showing Password Characters

The characters typed in a password input field are usually never shown because browsers blur characters in input fields with the type attribute set to password. That has been the standard behavior for over a decade and nobody ever complained much. A few years ago, though, some web sites started offering the option to type the password as clear text.

I wouldn’t definitely say it is a security hazard even though someone reading over your shoulder can easily catch a glimpse of your password. Switching between hidden and clear text characters is a user-friendly feature you might wish to consider.

In terms of code, all you need to do is to programmatically change the value of the type attribute of the input field. You can have a checkbox in the page and react to the user’s clicking on it by switching between the password and text value for the type attribute. Here’s some code.

When this JavaScript code is attached as an onclick event handler on a checkbox within the page, it verifies the checked status of the control and changes the value of the type attribute accordingly. The effect on the user interface is immediate: as soon as the type attribute is changed, the text is blurred or rendered as clear text. In general, you don’t want to save the checked status locally (cookie or local storage) as a user preference. The password field should default to type=password unless users turn clear text on for a few moments.

Suggesting New Random Passwords

In the view where users are entering a password to register with the site, or are just changing their current password, you might also want to offer a button that suggests appropriate passwords. A suggested password is typically unintelligible and randomly generated. Here’s a sample algorithm you can use.

The function picks a random character from the list of digits and lowercase and uppercase letters until it has constructed a string of the requested length. Needless to say, the algorithm can be made less predictive by providing an initial alphabet where digits, lowercase and uppercase letters are mixed up instead of being laid out one block after the next.

The resulting password is analogous to those that are automatically generated by most systems when you (or the admin) force a reset. In other words, it’s a password that will probably be changed soon for something that is easier to remember. So why having such a feature in a view? Some users will probably use one of the auto-generated passwords in order to get a password that is clearly a strong one.

I wouldn’t recommend suggesting passwords that are not automatically generated. Suggesting passwords from an existing list of strings and phrases might not be a good idea as several users might end up picking the same password. Anyway, this is a point on which only the direct knowledge of users and personal feelings really count.

Emailing Users After a Password Change

A password change is never a secondary event in a multi-user software system that requires authentication. For this reason, every time that users change their passwords you should email back the details of the operation. That represents an official communication from the system that a new password has been registered. At the same time, it represents a reminder for the user. Needless to say, communicating the new password via email is never a good idea.

Maintaining the History of Used Passwords

All of the features considered so far are common in most memberships systems whether created from the grounds up for a specific application, or adapted from one of the frameworks provided by Microsoft. Another feature that’s good to have is that of storing the list of passwords that a given user adopted in a given amount of time. Typically, users don’t much like having to change the password frequently (by the way, every six weeks is a good balance between security and bother) so they tend to re-enter the same password over and over or they just change it a bit, for example adding a progressive number to the end.

You should consider adding a string matching algorithm to your application so that whenever a new password is submitted it is checked against the stored list of previously used passwords. The check can be done only for equality or for closeness. For example, the password “foobar” is different from both “foobar1” and “fobbar”, yet the closeness between strings can’t be denied. Some web sites also force users to change the current password with one that is significantly different from any other password that was recently used.

The Levenshtein distance (see http://www.levenshtein.net/) is an algorithm you can use purposely that counts the number of edits required to turn one word into another one. If the calculated Levenshtein distance is below a small number (say 3) you can deny the password because it too similar to an old one.

Note that maintaining a history of previously used password is in contrast with hashing passwords. An effective hash, in fact, is not reversible so all that you can do is checking whether the exact password was used in the past. You have not much chances to check for password closeness. If that feature is required, then you should look for storing passwords through a reversible form of encryption.

Summary

Gone are the days when it was a simple matter to change a password by storing a new alphanumeric string in a database table column. These days, arranging an effective password-change view is much more complicated matter with more functionality to implement, including hashing, list of past passwords, email confirmation, auto-generation of random passwords and assessing the quality of password being typed. Hopefully, this article serves as a reference for the most important things to do to arrange the user experience. The real level of security is specific of the application and this-and only this-should drive the adoption of specific technologies and solutions.