Understanding And Implementing Password Hashing In NodeJS. 
Tags: node, javascript, cybersecurity, npm
Published: 2020-10-23 19:45:19

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/hqi9a43ne3gif4a9cp9n.gif)

It is the user's responsibility to have a strong password, but as a developer, it is our responsibility to keep their passwords secured. We've learned it in *Cybersecurity 101* - "Never, for the love of god, ever save the password in the form of **plain text** in your database. Always **Hash** it before saving". And it makes sense right? Password is a very, if not the most, sensitive and confidential information that a user is trusting the application with. It is possible that they might have the same password on any other platform, maybe even on any banking websites. It would be a disaster if someone else gets hold of the user's password, that too in plain text.

## What exactly is Password Hashing?
**Hashing** basically means to transform the data into a string of fixed length using a hash function. This transformation is irreversible. The process is simple,

![Hashing](https://dev-to-uploads.s3.amazonaws.com/i/8s84f33cpdgev3648hcq.png)

It is similar to _Encryption_, but with one difference i.e. the encrypted text can be decrypted using the _Cryptographic keys_, but it is nearly impossible to get the original string back by just having the hashed string. You can also call it as _"One Way Encryption"_ just to remember it easily. 

[Click here](https://medium.com/swlh/the-difference-between-encoding-encryption-and-hashing-878c606a7aff#7ac5) to read my article on Medium where I have explained the difference between Encoding, Encryption and Hashing in detail.

## Let's Implement a small program to understand it better.
```javascript
const crypto = require('crypto')

const md5sum = crypto.createHash('md5');
let str = "Hello";

const res = md5sum.update(str).digest('hex');
console.log(res);
//8b1a9953c4611296a827abf8c47804d7
```
In the above code snippet, we have hashed a string using the _**md5**_ hashing algorithm in JavaScript.
**_Please note that_**, the hashed string that we are getting as the output is unique to the input string "Hello", it is nearly impossible to find any other string producing the same hash. 

Just having just a hash only lets you verify the _authenticity_ of the data. What I mean is, if you have the hash function and you pass the plain text through it, you'll get the hash value, and once you compare the generated hash value with what was stored in your database, then only the authenticity of that data can be validated. 

But we need more than just that. We also need to verify the originator of the data along with it's authenticity i.e. we want to make sure that the entity passing the plain text to generate the hash for comparison is the same who originally generated it. This way we can make sure that it is the intended user only and not any unknown attacker. For that we use another technique called **_HMAC (Hash-based Message Authentication Code)_**. This adds an extra layer of security for storing the password.

HMAC uses a _Secret key_. This secret key is used to create the hash, such that if any other key is used in the same hash function for the same text, the generated hash will be different. This ensures that the hash is being generated by a genuine entity.

Let's look at the code to understand better:

```javascript
const crypto = require('crypto');

const hashingSecret = "ARandomSecretKey";
const plainText = "Hello World!";

const hashedStr = crypto.createHmac('sha256', hashingSecret)
                        .update(plainText)
                        .digest('hex');

consdole.log(hashedStr);
//a08116905e92633e4f30e53fq276206b25930rta383642fc5b7f51c089187939
```

Now, if we want to regenerate the same hash for the `plainText = "Hello World!"`, then we would require the same secret key i.e. `hashingSecret = "ARadnomSecretKey"`.

Okay, if I hash a password before storing it inside our database, so even if the hacker/attacker gets hold of the hashed password, I need not to worry. Right?
I wish this was true. Attackers can use _Brute-Force_, _Dictionary_ or _Rainbow Table_ attack to crack the hashed strings. 

> ##### FYI
> - _Brute Force attack_, works by calculating the hash function of every string present with them, calculating their hash value and then compare it with the one in the computer, at every step.

> ![Bruteforce](https://dev-to-uploads.s3.amazonaws.com/i/2dh7evur0kgqrj7wzu4o.jpg)

> - _Dictionary attack_ is the simplest form of attack possible on a hash function. We simply store for each possible input the corresponding hash. Then, given a hash, we can look it up in our database, and find the matching input.

> - A _Rainbow Table_ works by doing a cryptanalysis very quickly and effectively. Unlike bruteforce attack, a rainbow table attack  already computes the hashes of the large set of available strings and stores it in a rainbow table. 

> ![Rainbow](https://dev-to-uploads.s3.amazonaws.com/i/w8ibejl0fkbqczs9hgl1.jpg)


Is there any way to avoid this? Answer is **_Yes_** there is, but it's a bit _salty_.

## What is Salting?
No, it does not mean adding salt to you hash browns. Actually, **_Salting_** is a technique used in the hash generation process, to make the generated hash more secure. In salting, _random data_ is added to the input string, then the combined string is passed through the hash function to get a unique hash. This generated hash will be _different even for the same set of inputs_.

![Salting](https://dev-to-uploads.s3.amazonaws.com/i/0q5yy52cmaccds8qw1gu.png)

And as you can guess, by doing so we are making the process of the attacks like Dictionary and Brute-force, very very slow as all the generated hashes are unique.

Let's understand it using code. In the code below, we'll be using a npm module called **_bcrypt_**. Since the methods are [Asynchronous](https://blog.usejournal.com/everything-you-need-to-know-about-event-loop-in-javascript-1f14f94e5ab6), we'll be using the _promise_ approach to understand the different methods.
Follow the below steps before writing the code:
```bat
:~$ mkdir hashing
:~$ cd hashing
:~/hashing$ npm install bcrypt
```
- Step 1: Import the module
```javascript
const bcrypt = require('bcrypt');
const saltRounds = 10;
const plainText = "Hello World";
```
- Step 2: Generate the Salt using ``bcrypt.genSalt`` method
```javascript
bcrypt.genSalt(saltRounds)
  .then(salt => {
    console.log(salt);
    //Output: $2b$10$uuIKmW3Pvme9tH8qOn/H7u
    //A 29 characters long random string.
  });
```
- Step 3: Inside the genSalt callback, call ``bcrypt.hash`` method
```javascript
bcrypt.hash(plainText , salt)
 .then(hash => {
   console.log(hash);
   //Output: $2b$10$uuIKmW3Pvme9tH8qOn/H7uZqlv9ENS7zlIbkMvCSDIv7aup3WNH9W
   //A 61 character long string (notice that the 1st part of the string is actually the salt.
 });
```
- So, if I combine the above code snippets into one, it'll be as below:
```javascript
const bcrypt = require('bcrypt');
const saltRounds = 10;
const plainText = "Hello World";
bcrypt.genSalt(saltRounds)
 .then(salt => {
    bcrypt.hash(myPlaintextPassword, salt)
      .then(hash => {
        console.log(hash);
      });
 });
```

There is another way to generate the hash using ``bcrypt.hash`` function. In this approach the salt is auto generated and we just need to pass the ``saltRounds`` directly to the ``bcrypt.hash`` function.
```javascript
bcrypt.hash(myPlaintextPassword, saltRounds)
 .then(hash => {
    console.log(hash);
 });
```

- Okay, so a Salted Hash is generated and stored in the DB during sign-up. Now when a user wants to login, we need to match the password entered by the user, with what is stored in the DB.
bcrypt module provides another method called ``bcrypt.compare`` to compare the input string with the hashed string.
```javascript
// Load hash from your database for the password.
bcrypt.compare(loginPasswordString, hash)
 .then(result => {
    console.log(result);
    // This will be either true or false, based on if the string
    // matches or not.
 });
```

> Note: When we are hashing the data using _bcrypt_, the module will go through a series of rounds. This is done to return a secure hash. The value that you provide as the ``saltRounds``, _bcrypt_ will go through ``2^saltRounds`` iterations. This makes the algorithm slower than any other hashing algorithm, and hence making it more secure as it also increase the time that an attacker has wait for cracking the hashed using _brute force_, _dictionary_ or _rainbow table_ attacks (sometimes even more than a year).

Read more about _bcrypt_ module [here](https://www.npmjs.com/package/bcrypt).

## In Conculsion:
- Passwords must always be stored as _Hash Value_ in the database and not in _Plain Text_.
- We can use _crypto_ module in NodeJS to implement different Hashing Algorithms like _md5_, _sha264_, _hmac_ etc.
- _Salting_ is a process in which a random string is added to the plain text before it is passed to the hash function to get a more secure hashed string.
- _In my opinion_, we must always use _bcrypt_ module in NodeJS, as it allows Salting the hash, which makes it more secure and much more difficult for an attacker to crack it.

> Follow me on [Twitter](https://twitter.com/whoadityashukla), [GitHub](https://github.com/aditya278), and [Medium](https://medium.com/@aditya.shukla278) for more content or just visit to say _Hi_.

![A Cat GIF for no reason at all](https://dev-to-uploads.s3.amazonaws.com/i/yyhpskz2ix6f0ghda8e7.gif)