Today TutsPlus Premium got hacked. They used a third party plugin that stored passwords in plaintext. This is ironic, because NetTuts+, a sibling company posts about security once in a while. It’s also very frustrating for users (both present and past) because they have to change their password not only on Tuts+, but other sites as well.
If you’re storing passwords in plaintext, please stop for the sake of your users and your company/product. I’m going to show you that it’s easy to implement securing your user’s password.
An Introduction To bcrypt
I personally use bcrypt to hash all my passwords. It’s a hash that incorporates a salt (to protect against rainbow attacks) and is adaptive, meaning it can be made slower over time (as computers speed up) to protect against brute-force attacks. This is by far the most recommended hashing function out there because of these features. I’ll show you how to implement it in both PHP and Ruby.
If you are using PHP 5.2 or earlier, you may not have bcrypt available to you. In these versions it was implemented on the system side rather then in PHP itself (as in 5.3 and later). You can check if it is available on your system.
To implement, we’ll use PHP’s crypt function. This supports different varieties of hash types, and what one will be used is based on the salt.
Bcrypt’s salt starts with ‘$2a$’ followed by a two digit cost, another ‘$’ and 22 characters from ‘./0-9A-Za-z’. The cost parameter relates to how much load it will take to crypt the password. You’ll have to find a number (04 to 31) that isn’t too slow or too fast on your system. Here are two different ways to generate a bcrypt salt.
secure_generate_salt is a little more secure as it used openssl to generate a random string, but you will need the openssl extension enabled.
Once you have a salt, hashing your password is simple.
Now you’re storing secure passwords, congratulations. But how do we verify if the user’s input matches our stored hash?
As simple as that. If you put that together in a class, you can have a really handy tool.
Why yes there is a bcrypt gem, which makes it super simple to implement in your application. Install it with
gem install bcrypt-ruby and require
Generate a hash with
And verify a password with
Since you’re not storing passwords in plaintext anymore, you won’t be able to send passwords in emails if someone forgot theirs. Instead you’ll have to build a password reset system. You could either have a temporary link or generate a random password and send it to them or another method.
If you find that the costs you’ve been using are either too fast or too slow you can’t just change the cost parameter in the hash. You can instead rehash the password on a successful login using your new cost.
So Why Aren’t You Using bcrypt?
As you can see, bcrypt is both secure and easy to use. You have no good reason to continue storing passwords in plaintext.
Comments? I'm @mloberg on Twitter.