Our Objective
Here's the picture, You are creating your web application that takes in user information, It could be things such as Credit Card Number, National Identification Number, or even Password e.t.c But when you save it, you still get the raw user data being stored exactly the way it has been inputted. How do we go about hashing certain user information so that we can better secure our data?
Data like these are typically stored in a database, and we need a way to encrypt such data so that it doesn't become easily accessible. Even If someone were to hack our database, all they would see is just a bunch of hashed data they can't do anything with.
Our Development Tool
We would be using the bcryptjs library to achieve this goal, It is a very secure and widely used hashing algorithm, which has a lot of cryptographical use cases. This library will help us solve our security problem. You can click here to learn more about the library.
Prerequisites
Basic Understand of Arrow Functions.
Basic Understanding of Command Line/Terminal.
Async - Await.
Node is installed
What is Hashing?
Hashing is the process of transforming any given key or a string of characters into another value. This is usually represented by a shorter, fixed-length value or key that represents and makes it easier to find or employ the original string.
Getting Started
To kick things off, we need a separate file, where we would be storing the logic for our hashing algorithm, this would serve as the playground for understanding how this library works, Before we implement it in our application.
Go ahead and initialize a directory/folder and then create your JavaScript file inside it. My folder name is models and my filename is index.js
.
We would start by installing bcrypt into our project folder by using our terminal. We can run the code below to install bcrypt:
npm i bcryptjs
You should have this result printing:
Writing our Logic
Before we start hashing our data, we need to require the bcryptjs library into our index.js
file, this gives us access to the functions necessary for our goal. You can write the code to save the library into a variable.
const bcrypt = require("bcryptjs")
Next, we need to create an Async function that would help us work with the promises that would be returned from bcryptjs, This is because it is a promise based library. Let's create an async function.
I would call mine, myFunction()
and invoke the function afterwards.
const myFunction = async () => {
}
myFunction()
You can learn more about async-await in my article
Hashing Data
Let us go ahead and create the information we are trying to hash, we'll be using user password as an example, I would create a variable for this password. We would assume it to be the plain text password our user provides to us.
To get this done, type the code below:
const myFunction = async () => {
const password = "John2468$"
}
myFunction()
Below this code, we are going to be creating the hashed version of this password by using bcrypt .hash() method. This method returns a promise containing the hashed version of our password and we would await it's value and store it in a variable called hashedPassword
.
The .hash() method takes in two arguments, The first being the data to be hashed, in this case our user password, which we have access to via the password variable. The second being the number of rounds we want to perform.
The number of rounds determines how many times the hashing algorithm is going to be executed, Based on my experience with the library i find that a very good number for this is 8, as it strikes a good balance between security and speed. If we use a lesser number of rounds, the algorithm becomes easy to crack and if we use too many rounds, the algorithm takes a long time to run.
Here's the code to make this happen:
const bcrypt = require("bcryptjs")
const myFunction = async () => {
const password = "John2468$"
const hashedPassword = await bcrypt.hash(password, 8)
console.log(password);
console.log(hashedPassword);
}
myFunction()
When we go ahead and log the result of password and hashedPassword, we get the result printing below:
We see that the hashing algorithm has hashed our data successfully!
The hashed version is what we would be storing in our database.
This is the hashed version of our data and is exactly what we'll be typically storing in our database where we have password.
Hashing Algorithms Vs Encryption Algorithms
When we use encryption algorithms, we can get the original version of our encrypted data back, This is sort of like a reversible process.
(encrypted) (reversed)
data ---------> 12&#errr!@#$uihh$7 ---------> data
In the case of hashing algorithms, we are dealing with a typical one way algorithm which is irreversible once hashing has occurred.
(encrypted)
data ---------> 12&#errr!@#$uihh$7
Now, this is by design, and in this article we are dealing with hashing, which begs the question, How do we go about logging in, so we compare the credentials provided by the user with the one stored in our database just to be sure they are exactly matched.
Comparing Data
bcryptjs gives us a way to compare our stored value, with the one the user would provides when using our API, We would be using the bcrypt.compare()
method, which takes in two arguments:
The data to be hashed and compared. i.e user input
The hashed value of that data e.g hashedPassword
Although we are typing this out manually, when we are building api's it would be taken from the users and not just typed by us.
We would create a variable called isMatch and we would use the .compare()
method on bcrypt and then pass in the required values, i.e user input and the hashed version we have stored.
Now, we can type the code to get this done, See the code below:
const bcrypt = require("bcryptjs")
const myFunction = async () => {
const password = "John2468$"
const hashedPassword = await bcrypt.hash(password, 8)
console.log(password);
console.log(hashedPassword);
const isMatch = await bcrypt.compare("John2468$", hashedPassword);
console.log(isMatch);
}
myFunction()
When we run our file again, we should get the boolean called true printing.
Behind the scenes bcrypt has run its hashing algorithm on the user password data, and when compared to the hashedPassword, it shows it to be an exact match.
When we change the value provided such as changing "J" in "John" to "j" we would get a different output printing.
const bcrypt = require("bcryptjs")
const myFunction = async () => {
const password = "John2468$"
const hashedPassword = await bcrypt.hash(password, 8)
console.log(password);
console.log(hashedPassword);
const isMatch = await bcrypt.compare("john2468$", hashedPassword);
console.log(isMatch);
}
myFunction()
This is typically what we would need when we are building our applications, it could be a system where users are required to login and you want to compare the password they have provided, with the one you have in your database. This is a highly recommended way of storing such data.
Conclusion
So far we have seen how to hash certain user data before storing them in our database, using the .hash()
method of the bcryptjs library where we have to provide the user data and the number of rounds.
We also covered how to compare values with each other using the .compare()
method as well.
To see the implementation of this in an actual project, I used bcrypt while building my REST-API-WITH-MONGOOSE project to secure user password, here's a link to the github repo
Top comments (2)
This is so accurate
Thank You