NB-1: This is the first post in a series of posts on web application security.
I’m assuming we’re talking about web apps, and most web apps have user accounts, and most of those have passwords. That is: I’m assuming you’re storing passwords.
Password storage is in the news pretty constantly because people keep doing it wrong, storing passwords…
- …in plain text.
- …with simple MD5 hashes.
- …or using any fast hashing function.
Fortunately, The Right Thing™ is easy. (Unfortunately, many of the apps you use every day are doing The Wrong Thing™ and you just don’t know it yet.)
Why is it important to do The Right Thing™ even if you’re not running a big app? Because users do dumb things. They reuse passwords, including the passwords to their email address and bank accounts. You should assume that at some point, someone will have your user database, and if they can easily extract an email address and a password, they’ve basically got a user’s entire identity.
So what is The Right Thing™?
- Use a cryptographically slow hash function. bcrypt and PBKDF2 are excellent choices. Even if someone has complete access to your database, it’ll take a long time (longer for longer passwords) to calculate these, and as processors get faster, they both have a work factor that can be increased, so the time to generate each hash can remain constant.
- Use HMAC with expirable keys stored on the filesystem (or anywhere outside the user database). This way, even if the users get the database (which often happens via a SQL-injection vector) they still also need to compromise the file system or settings information.
Libraries like django-sha2 will do all of this for you. (Ignore the name, it’s a historical artifact: it uses bcrypt and HMAC.) They exist for most frameworks, so you shouldn’t have to roll your own.
Which is a final thought: unless you have a Ph.D in this, never roll your own crypto. And even then, you probably want something tested by the community and other experts.