by Nathan Sebhastian
Posted on May 09, 2021
Reading time: 5 minutes The When the user submits a password, the password will be hashed and your JavaScript application needs to store the hash in the database. Later when the user wants to authenticate his or her account, you need to compare the password input with the hash stored in your database to see if it matches. The To start using the library, you need to install it with your package manager: Then include the module to your JavaScript code with To generate a password using the Here’s an example of Or you can use the synchronous method equivalent called A hashing function requires you to add salt into the process. A salt is simply a random data that’s used as an additional input to the hashing function to safeguard your password. The random string from the salt makes the hash unpredictable. In the code examples above, the salt is auto-generated by To generate a salt, you can use the Once you have the salt, you can pass it to the bcrypt
npm package is a JavaScript implementation of the bcrypt password hashing function that allows you to easily create a hash out of a password string
. Unlike encryption which you can decode to get back the original password, hashing is a one-way function that can’t be reversed once done.bcrypt
library makes the process easy by providing you with methods to hash and compare passwords.npm install bcrypt# oryarn add bcrypt
require
:const bcrypt = require("bcrypt");
Creating a password hash with bcrypt
bycrypt
module, you need to call on the hash()
method which accepts the following three parameters:string
that you wish to hashnumber
of rounds to secure the hash. The number commonly ranges from 5 to 15callback
function to execute when the hash process is finished, passing along the error
message and the hash
resultbcrypt.hash()
processing the password string "generic"
:const bcrypt = require("bcrypt");bcrypt.hash("generic", 5, function (err, hash) { console.log(hash); // TODO: Store the hash in your password DB});
hashSync()
:const bcrypt = require("bcrypt");const myPlaintextPassword = "generic";const hash = bcrypt.hashSync(myPlaintextPassword, 5);console.log(hash);
Generating salt for the hash
bcrypt
module, but you can actually generate the salt first before hashing the password.genSalt()
method from the module:const bcrypt = require("bcrypt");bcrypt.genSalt(10, function (err, salt) { console.log(salt); // the random salt string});
hash()
method as follows:
const bcrypt = require("bcrypt");bcrypt.genSalt(10, function (err, salt) { bcrypt.hash("generic", salt, function (err, hash) { console.log(hash); // Store hash in your password DB. });});
There’s also a synchronous equivalent for the method called genSaltSync()
:
const salt = bcrypt.genSaltSync(10);const hash = bcrypt.hashSync("generic", salt);
Note that there’s no differences on the resulting hash whether you generate a salt separately or automatically, but the CPU usage may be lowered when you separate the salt generation and the hash process. You should test if your NodeJS server can handle auto-generating the salt and hash first before separating them.
A note on the salt round number
The salt generation for your hash function can range from a few seconds to many days, depending on how many rounds you passed. The bcrypt
module will go through 2^rounds
to generate the salt to give you a secure hash.
According to the documentation, here’s the amount of time to process the salt generation on a 2GHz core computer:
rounds=8 : ~40 hashes/secrounds=9 : ~20 hashes/secrounds=10: ~10 hashes/secrounds=11: ~5 hashes/secrounds=12: 2-3 hashes/secrounds=13: ~1 sec/hashrounds=14: ~1.5 sec/hashrounds=15: ~3 sec/hashrounds=25: ~1 hour/hashrounds=31: 2-3 days/hash
The number is just an estimation, so you may want to test the highest rounds with the fastest generation time that your server can support.
Verifying a password with bcrypt
Once you saved the hash to the database, you can compare the user’s plain text input with the stored hash using the compare()
method.
The compare()
method accepts three parameters:
- The plain
string
password for comparison - The hash
string
created earlier - And the
callback
function once the comparison process is finished
The method will pass the error err
object and the boolean value result
, telling you whether the comparison matches or not.
Here’s an example of the compare()
method in action:
const bcrypt = require("bcrypt");bcrypt.hash("generic", 5, function (err, hash) { console.log(hash); // The hash returned, continue to compare bcrypt.compare("generic", hash, function (err, result) { console.log("generic:", result); // generic: true }); bcrypt.compare("falsy", hash, function (err, result) { console.log("falsy:", result); // falsy: false });});
The module also provides the synchronous method compareSync
for you to use:
const bcrypt = require("bcrypt");const myPlaintextPassword = "generic";const hash = bcrypt.hashSync(myPlaintextPassword, 5);const result = bcrypt.compareSync(myPlaintextPassword, hash);console.log(result); // true
After the comparison is finished, you need to provide the right authentication code according to the returned result.
Using promise or async/await instead of callback function
Finally, bcrypt
module also supports the use of promise and async/await code style, so you can use them instead of callbacks to make your code cleaner.
Here’s an example of using promises in the hash process:
const bcrypt = require("bcrypt");bcrypt .hash("generic", 5) .then((hash) => { return bcrypt.compare("generic", hash) .then((result) => { console.log("generic:", result); // generic: true }); }) .catch((err) => { console.log(err); });
And another example using the async/await style:
const bcrypt = require("bcrypt");async function passwordHashTest(password) { const hash = await bcrypt.hash(password, 5); const result = await bcrypt.compare(password, hash); console.log(result); // true}passwordHashTest("generic"); // test the async function
And that’s how the bcrypt
module in NodeJS works 😉