
When dealing with user account information, there are lots of different security concerns that come up. Some examples include making sure users use strong passwords, preventing automated registrations, helping end users distinguish real sites from phishing sites, transmitting user data securely, and so forth—the list goes on and on.
In this article we're going to look at a specific piece of the overall user account security puzzle, and that's the problem of storing user passwords securely. Specifically we will see how you can use techniques from cryptography—hashing and salting your passwords—to make it harder for would-be attackers to uncover user passwords in the event that the password database (or password file, or whatever) is compromised.
We're only going to cover the concepts and techniques here; we won't get into how to actually implement this on any particular platform or using any particular framework. My brother John and I are currently writing a book for Manning Publications called Spring in Practice that will explain how to implement password salting and hashing using the Spring Framework, but for this article we'll just look at the concepts and techniques.
Also, a disclaimer is in order. I'm not a security expert of any kind, so if you are doing something requiring expert advice, please seek that out.
It's worth thinking for a moment whether it's really even necessary to "store user passwords securely," if doing so involves anything more than limiting access to password data. If only a small number of trustworthy technical staffers have access to the user passwords, then why can't we just store the data in the clear? Doesn't that make it easier for technical staff to troubleshoot system issues (for example, admins can just log in as other users to try to reproduce errors), and doesn't that make it easier to help users recover forgotten passwords?
The answer to both of those questions is yes, but the story doesn't end there. The problem is that storing plaintext passwords also makes it easier for bad guys to see user passwords, and that's true whether bad guys break in from the outside or whether you have bad guys on your admin team. If attackers can log into your applications under somebody else's account, that's potentially very bad for you and your users. Moreover, because users often have the bad habit of reusing passwords (or else simple variants of passwords) across multiple applications and web sites, it's very difficult for you to limit the scope of the damage once somebody actually gets ahold of user passwords. The situation is possibly very damaging to your users and embarrassing to your organization. In all but the most trivial cases, it makes a lot of sense to store user data securely.
As an aside, note that in doing so, we don't give up the ability to allow admins or tech support reps to impersonate other users, nor do we sacrifice the ability to help users who have forgotten their passwords. We just have to use other techniques to accomplish those things, such as "run-as" impersonation, and using password resets in lieu of password recovery. Let's however stay focused on storing passwords securely.
So now we've seen why we don't want to store plaintext passwords. In the rest of this article we're going to look at four increasingly sophisticated cryptographic techniques for making it harder for attackers to get at your passwords. All four are based on something called a hash function, so let's start by talking about hash functions a bit.