Using Bcrypt To Hash & Check Passwords In Node.js
Chances are that you'll need to handle people's passwords in your coding endeavors. Since it's a big no-no to store passwords as plain text in your database, how are you supposed to handle and store them?
The answer is to generate a hash (a long, complex, and unique string) using the user's password and store that hash in your database. Later on, you can compare the hash and password to verify that they match.
If your database gets hacked in this case, the hacker will be left with random hash strings instead of plain text ones they could use to easily exploit your user's accounts with.
The only way to find the password or message that produces a given hash is to attempt a brute-force-search of possible inputs to see if they produce a match. Or use a rainbow table of matched hashes. If you generate your hashes correctly, both methods would take a hacker lots of time and tons of computing power to complete.
In this article, we'll walk through how to hash a password using the Node.js implementation of Bcrypt called bcrypt.js.
Bcrypt is one of the most used encryption libraries today. It incorporates hash encryption along with a work factor, which allows you to determine how expensive the hash function will be (i.e. how long it takes to decrypt it by brute force measures). Therefore it keeps up with Moore's law, so as computers get faster you can increase the work factor and the hash will get slower to brute force.
Before moving forward, make sure you have Node.js installed and an application directory setup for our code.
If needed, we wrote a guide on installing Node.js.
Let's get started!
Table Of Contents
Install The bcrypt.js NPM Package
Before we can start writing our code, we need to install the bcrypt.js NPM package.
You can install it with one of the below commands:
NPM:
npm install bcryptjs --save
Yarn:
yarn add bcryptjs
When that's done installing, we're ready to for the next section!
Hash A Password
Now we can hash a password and see how this all works in practice!
We'll show you all the code upfront and explain each part afterward.
Here's the full code:
const bcrypt = require("bcryptjs")
const password = "mypass123"
const saltRounds = 10
bcrypt.genSalt(saltRounds, function (err, salt) {
if (err) {
throw err
} else {
bcrypt.hash(password, salt, function(err, hash) {
if (err) {
throw err
} else {
console.log(hash)
//$2a$10$FEBywZh8u9M0Cec/0mWep.1kXrwKeiWDba6tdKvDfEBjyePJnDT7K
}
})
}
})
There's a lot going on here, so let's break it down.
First, we create two variables named password
and saltRounds
.
The password
variable will be the string bcrypt hashes.
And the saltRounds
integer gives us control over what the computing cost of processing the data will be. The higher the number, the longer it will take a machine to calculate the hash associated with the password. So, we want to choose a number that is both high enough to make a brute force attack take too long and short enough to keep the end user's patience from ending when signing up or logging into their account. 10
is the default saltRounds
value.
We then do two things in sequence to generate our hash:
- Generate a salt using our
saltRounds
integer. - Create a hash string for our password of
"mypass123"
.
We use the bcrypt.genSalt()
function to generate the salt. The function takes our saltRounds
integer of 10
as a parameter and returns a callback function with the generated salt result.
And we use the bcrypt.hash()
function to generate the hash. It takes our "mypass123"
password and the salt we generated as parameters. In the callback function, it returns the generated hash string for our password.
When you run the code, the hash should be printed to your command line and look similar to this:
$2a$10$FEBywZh8u9M0Cec/0mWep.1kXrwKeiWDba6tdKvDfEBjyePJnDT7K
This is the string you would store in your database instead of the password in plain text form.
Pretty awesome, right?!
But wait! How do we check a user's password against the hash when we want to authenticate or log in a user? We'll show you how to do that next.
Check A User Entered Password
Now that we've hashed our password, we need a way to compare it to a string entered by a end-user and see if it matches the original password entered for that account.
Luckily, Bcrypt has a built-in way to do this! Like before, we'll show you the full code and then explain everything afterward.
Full code (make sure you replace YOUR_HASH_STRING
with the hash we generated in the last section):
const bcrypt = require("bcryptjs")
const passwordEnteredByUser = "mypass123"
const hash = "YOUR_HASH_STRING"
bcrypt.compare(passwordEnteredByUser, hash, function(err, isMatch) {
if (err) {
throw err
} else if (!isMatch) {
console.log("Password doesn't match!")
} else {
console.log("Password matches!")
}
})
Let's break down each part of the code.
First, we create two variables called passwordEnteredByUser
and hash
. passwordEnteredByUser
represents the password a user would type in a login form and is what we will compare to the hash we generated in the last section.
Then, we use the bcrypt.compare()
function to compare the passworedEnteredByUser
and hash against each other. It has a callback function that returns the true
/false
result of whether or not the two matched. We then log success or failure messaging based on whether isMatch
has a true
or false
value.
If everything went as planned, you should see this message in your console when you run the code:
Password matches!
Sweet! You just match a password with its hash counterpart!
But we should make sure other password strings fail. To test this, change the passwordEnteredByUser
value to anything besides "mypass123"
:
. . .
const passwordEnteredByUser = "BigBoi123"
. . .
When you run the code again with the new passwordEnteredByUser
value, you should see this output in your terminal:
Password doesn't match!
There you have it! You now know how to hash a password in Node.js using the JavaScript implementation of the Bcrypt library.
Hopefully, this article has helped you secure your applications and assisted in achieving all your coding dreams!
As always, thanks for reading!