HomeFrameworksNodeJSNodeJS Hash Password using BCrypt

NodeJS Hash Password using BCrypt

Are you a developer working on a Node.js application which requires you to provide the functionality of login and registering users. You also want to hash password before saving them to the database. Recently, while working on a similar kind of project we were in the same position and then we recognised the features of BCrypt module to hash passwords. Now taking not much of your precious time, lets quickly dive into understanding this journal entry “Nodejs Hash Password using BCrypt“.

Node.js Hash Password using BCrypt

In this journal entry we’ll not be comparing the different ways of storing passwords. Instead, we’ll be looking at the implementation of salt hashing mechanism for storing passwords in NodeJS. You can be rest assured that this is one of the better ways to store passwords if not the best way.

What is Salt Hashing?

Salt hashing is a technique where we combine the user entered password and a random string with a suitable hashing algorithm. Here the random string of characters are called as salt. Once we get the final result of the combined string and the hashing algorithm we got ahead and store the results in database.

Why Salt Hash?

MD5, SHA1, SHA256, SHA512, SHA-3 are all general purpose hash functions, designed to calculate a digest of huge amounts of data in as short a time as possible. Hashes generated of the same password text are same, they become much easier to crack using rainbow tables or lookup tables. So, if two or more users have the same password, it becomes very easy to predict the password for the attackers. As a rule of thumb, no two or more users should be having the same password hash. Adding salt to a password and then hashing the result reduces the possibility of having duplicate hashes and if your salt length is long enough, chances are minimal.

Understanding BCrypt

Let’s look at the implementation of one of the most popular salt hashing algorithm known as bcrypt.

bcrypt is a password hashing function designed by Niels Provos and David Mazières, based on the Blowfish cipher, and presented at USENIX in 1999.[1] Besides incorporating a salt to protect against rainbow table attacks, bcrypt is an adaptive function: over time, the iteration count can be increased to make it slower, so it remains resistant to brute-force search attacks even with increasing computation power.

Source: Wikipedia

The bcrypt function is the default password hash algorithm for OpenBSD.

Bcrypt specification defined a prefix of $2a$. This follows the Modular Crypt Format used when storing passwords in the OpenBSD password file:

  • $1$: MD5
  • $2a$: Bcrypt
  • $sha1$: SHA-1
  • $5$: SHA-256
  • $6$: SHA-512

Now lets take a practical look at implementation of bcrypt using NodeJS.

Practical Implementation

Lets first make sure that the version of node we are using is the latest and stable version. If you are not on the latest version then go ahead and check out the following journal entry Upgrade Nodejs Version.

Lets create a new NodeJS project where we will try to implement the bcrypt module for salt hashing the passwords.

Once the project is setup, lets issue the following command:


npm install bcrypt --save

The above command will install the bcrypt module locally in your project under the “node_modules” folder. The --save option here basically makes the changes inside your package.json file. In case you miss the --save option then you have to modify the package.json file yourself and make an entry in the “dependencies” block.

Usage

Ok, now that you have your project ready with the bcrypt module added, let’s see how are we gonna use this module.

async (recommended)

var bcrypt = require('bcrypt');
const saltRounds = 10;
const myPlaintextPassword = 'password';

To hash a password:
Technique 1 (generate a salt and hash on separate function calls):

bcrypt.genSalt(saltRounds, function(err, salt) {
    bcrypt.hash(myPlaintextPassword, salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

Technique 2 (auto-gen a salt and hash):

bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
  // Store hash in your password DB.
});

Note that both techniques achieve the same end-result.

To check a password:

// Load hash from your password DB.
bcrypt.compare(myPlaintextPassword, hash, function(err, res) {
    // res == true
});

with promises

bcrypt uses whatever Promise implementation is available in global.Promise. NodeJS >= 0.12 has a native Promise implementation built in. However, this should work in any Promises/A+ compilant implementation.

Async methods that accept a callback, return a Promise when callback is not specified if Promise support is available.

bcrypt.hash(myPlaintextPassword, saltRounds).then(function(hash) {
    // Store hash in your password DB.
});
// Load hash from your password DB.
bcrypt.compare(myPlaintextPassword, hash).then(function(res) {
    // res == true
});

sync

var bcrypt = require('bcrypt');
const saltRounds = 10;
const myPlaintextPassword = 'password';

To hash a password:
Technique 1 (generate a salt and hash on separate function calls):

var salt = bcrypt.genSaltSync(saltRounds);
var hash = bcrypt.hashSync(myPlaintextPassword, salt);
// Store hash in your password DB.

Technique 2 (auto-gen a salt and hash):

var hash = bcrypt.hashSync(myPlaintextPassword, saltRounds);
// Store hash in your password DB.

As with async, both techniques achieve the same end-result.

To check a password:

// Load hash from your password DB.
bcrypt.compareSync(myPlaintextPassword, hash); // true

Why is async mode recommended over sync mode?

If you are using bcrypt on a simple script, using the sync mode is perfectly fine. However, if you are using bcrypt on a server, the async mode is recommended. This is because the hashing done by bcrypt is CPU intensive, so the sync version will block the event loop and prevent your application from servicing any other inbound requests or events.

A Note on Rounds

When you are hashing your data the module will go through a series of rounds to give you a secure hash. The value you submit there is not just the number of rounds that the module will go through to hash your data. The module will use the value you enter and go through 2^rounds iterations of processing.

From @garthk, on a 2GHz core you can roughly expect:

saltRounds=8 : ~40 hashes/sec
saltRounds=9 : ~20 hashes/sec
saltRounds=10: ~10 hashes/sec
saltRounds=11: ~5 hashes/sec
saltRounds=12: 2-3 hashes/sec
saltRounds=13: ~1 sec/hash
saltRounds=14: ~1.5 sec/hash
saltRounds=15: ~3 sec/hash
saltRounds=25: ~1 hour/hash
saltRounds=31: 2-3 days/hash

Conclusion

If you are working on any web application that stores users password, it is very easy to get things wrong, here we saw how we can store passwords using salt-hash technique which is highly recommended, however it is a request to the readers to look up at recent techniques of storing passwords from the time you are reading this article.

RELATED ARTICLES

Most Popular