Hashing passwords in CFML

 

It’s easy to store passwords, it’s also easy to do it poorly.

It’s not enough to just hash(form.password) your users data, it’s a good first step but is horribly insecure.

Why do we hash passwords?

The main reason is that if your data is compromised, an attacker could get the users stored passwords.

People tend to reuse passwords and follow patterns, which means your data breach can compromise users data on other websites, or other parts of your own website.

Hashing is one-way, there’s no way to de-hash a value, you can only create a hash with your own data, and compare it to an existing hash in order to deduce the hashed value.

Of course, if you encrypt data and use secure hashes for keys, the data is also secure.

But why isn’t it enough to hash()?

Because of brute force and rainbow tables.

A rainbow table is a set of data with pre-computed hashes.

For example, the hash() for the string “password” is “5F4DCC3B5AA765D61D8327DEB882CF99”

Knowing that, we can compare the stored value against the known hash, and suddenly we know the password.

The first defense against this kind of attack is salting.

In effect it means that we modify the value we want to hash, for example by prepending “thisisasalt” to the password being passed in, so what’s actually being hashed is “thisisasaltpassword”, which gives a different hash from just “password”.

This means we can’t use existing rainbow tables, unless they’ve been calculated using the specific salt your site uses.

But hash() is still a very fast function, it’s easy to write a loop and create a new rainbow table when you know the salt value, so you can compromise the data.

We can fight this by using iterations, making sure the process takes a long enough time to compute that it takes a long time to create many hashes.

It’s a matter of computing power.

Over time, you can’t protect against brute force hashing but you can make it a very slow and computationally expensive process.

If it takes milliseconds to generate a hash, you can create many in the matter of a minute, but if it takes a second per hash, you can only create 60 hashes in a minute.

That’s 60 potential passwords, not guaranteed.

Now, that means that every time a user logs in, it takes a second extra for them to log in, so it’s a matter of user-experience versus security.

Taking a minute per hash is very secure, but no user is going to wait around for the login to finish, but a second or even a few is ok if it’s just during login.

It’s also a matter of hashing algorithm, SHA-256 is considered secure, if it’s used with iterations and properly salted.

An example of how we could implement this

var salt = "youshouldusealongsalt";
var password = "password";
var hashed = hash(salt & password, "SHA-256");

for(var i = 1; i < 200000; i++){
    hashed = hash(salt & hashed, "SHA-256");
}

How long that actually takes depends on your hardware, so adjust the iterations accordingly.

Another way of salting which is even better is to use dynamic salts.

If you have a user logging in, you can use salt & username to create a dynamic salt, that makes is magnitudes harder for anyone to compromise the data, because they can’t generate rainbow tables useable for more than a single user at a time.

Modifying the code above to use dynamic salts is very straight forward

var salt = "youshouldusealongsalt";
var username = form.username;
var password = "password";
var hashed = hash(salt & username & password, "SHA-256");

for(var i = 1; i < 200000; i++){
    hashed = hash(salt & username & hashed, "SHA-256");
}

It doesn’t take much work to amp up security for your website, and is well worth doing.

Leave a comment

Create a free website or blog at WordPress.com.

Up ↑

Design a site like this with WordPress.com
Get started