At Software Verde we pride ourselves on taking security seriously and always setting aside time to update ourselves on recent discoveries and current best practices. No matter the client, we always consider the safety of their data and how we can best ensure that their systems are stable, efficient, and secure. We are always practical but never take the easy route when it comes to making sure that our clients are protected from the ever-increasing threats to their data on the Internet.
This post is the first part of a series in which we will cover one way that we protect our clients' data: responsible password management. This is a topic that has evolved much over the years and where research is constantly being done. Given this, it is especially important that we regularly familiarize ourselves with the progress made in this field and use that knowledge to make informed decisions about how to best serve our clients.
To begin, we will take what might seem to some like a drastic step: the most responsible thing we can do with passwords is to not store them in the first place. This is common practice in modern software applications but is worth thinking through. The most obvious question, how can we check user's passwords if we don't store them, we will ignore for the time-being. Instead, let's first look at why storing the passwords is a bad idea, then where we can go from there.
For the sake of tangibility, let's assume we're not talking about a software system but a doorperson at a club who must receive a password specific to a particular guest before letting them in. If each person has their own password, the doorperson must keep a list of all possible guests and their passwords (let's assume there are too many people for the doorperson to remember). This means that the doorperson has a very valuable list in their possession, especially if there is a chance that the guests might use the same password to get into other clubs. If someone could break in and steal the list (or copy or take pictures of it) they would then be able to impersonate anyone on it.
This may lead some to suggest altering the message so that it is not easily readable by anyone other than the doorperson (i.e. encoding the password, as in the Caesar shift). However, someone with a copy of the list could spend as much time as they need figuring out this encoding process. In fact, no matter how complex the process, one should always consider the fact that a person with enough time and desire to get that information would eventually determine the method for decoding the data. This kind of practice of hoping that a theif would not be able to figure out exactly what process you used is known as security through obscurity and does not sufficiently protect the passwords.
Another possible approach would be for the doorperson to mix a password of their own with each of the other passwords in a way that would make it impossible to get the guest's password without the doorperson's password (i.e. encrypting the passwords). This is better but is ultimately only as secure as the doorperson's password. If the password is something easily predictable (e.g. the name of the building) then those who steal the list of encrypted passwords will again, provided they have the time and desire, be able to figure out the guest passwords. Alternatively, they could torture the doorperson (or otherwise try to get the password out of them) and accomplish the same thing. In the end, having the actual passwords is dangerous and, given enough time and sufficiently determined thieves, is likely to become an issue.
However, if the doorperson is not able to determine what the user's password should be, how can they know that the person should be allowed entry? If they can determine whether a person's password is correct, what keeps someone that steals the list from being able to learn the password. The methods for doing this effectively involve studying two related topics: one-way functions and brute-force attacks.
We will cover these topics in our next blog post. The conversation can get awfully mathy here (and it might still be a little mathy) but instead of going into every possible detail we're going to try to focus on the high-level approaches and why they work. After that we will discuss the modern approaches to solving these problems and our current recommendations for programmers.