Password Security with Rails
This week at Flatiron, we’ve been working on our module 2 projects. These are full-blown CRUD applications with all kinds of uses that use Rails for the back-end. For many of us, this was our first instance of implementing users as well as a log in system with passwords. For our passwords, most of us are using the ‘bcrypt’ gem. That way, the only thing we store from our users is the password digest, or hash.
From one of our examples in lecture, we saw how ‘bcrypt’ gives us a ‘unique’ hash every time we enter a password, even if the passwords were the exact same.
Great! But wait. How does this work? Why are they different? If I just use any old hashing algorithm, will all my passwords be protected? Let’s see. MD-5 is a hashing algorithm that’s no longer for cryptographic hashing, e.g. passwords. With the power of modern computers, “collisions” can be found in seconds using this algorithm. A collision is when two hashed items result in the same output. We don’t want to hash two different passwords and have the same resulting hash, we want our values to be unique. Using MD-5, we can learn why hashing only is insufficient.
So we generate a hash for our “password.” This looks pretty similar to what we did earlier with ‘bcrypt’, what’s the problem?
OH. Well that’s not good. How is ‘bcrypt’ generating secure hashes that are unique each time?
Salts! A salt is a random string of characters that get added to a password before it gets hashed. The password and string combo are then hashed together. Typically, the password hash and string are stored to the database and the input password is concatenated with the salt and the result is compared to the stored hash. If they match, you’re allowed access to your account. Additional security is gained by using a different salt for every single password.
In the end, this makes brute-forcing passwords through their hashes extremely difficult. A typical method would be to hash every word in a dictionary or list of common passwords. You can then compare those to your list of hashed passwords to try and find a match. Think about how difficult this would be if every single password was hashed with a salt. You would never find a match. If only.
‘Bcrpyt’ works in a very similar manner to the method outlined above. However, instead of storing the salt in the database, it gets stored in the hash itself. Let’s look at a hash for password. This is the result from the first password we hashed.
$2a$12$wv9ZGkUX0XglG3vDipajyOWg1rAxh7A2QxK.8.zna/1vzZno8VD3i
What does this string mean? The $ separates different pieces of information. After the first one is the version of ‘bcrypt’ being used.
After the next $ is the cost factor. In simple terms, the higher this value, the more computational power required to create the hash. This value can be changed from the default 12 in Rails to any value you want. If you desire more security, make it higher. Just remember that the computational toll is exponential. Moving from a cost of 12 to 14 will take roughly 4 times as long to generate the hash. Remember, this happens every time a user logs in, so we want to ensure it’s high enough to be secure, but so high as to upset our users.
Finally, after the final $, the first 22 characters are the plain text salt, followed by 31 characters which are the hashed salt and password combo. Let’s see another example.
Awesome. So when we enter the salt and the correct password, our hash would match our stored password digest! Again, even with the salt, the difficulty here comes in from the cost factor. ‘Bcrypt’ is intentionally slow. Even using a brute-force attack, only a few hundred passwords per second can be attempted. This isn’t slow enough for a user to notice when they login and only run through the algorithm once, but it’s more than sufficient to slow down malicious attempts to find a password.
Passwords, hashing, and protecting your users is a complicated, but important endeavor. Now that you know the basics, you’re better positioned to evaluate the tools you use you to keep your information safe and to keep the information of your users safe.