# How to hash passwords using Bcrypt in Node.js

By Atta Ur Rehman Shah (https://attacomsian.com/about). Published Nov 22, 2020, updated Oct 1, 2022. Topics: Node.js.
Canonical URL: https://attacomsian.com/blog/nodejs-password-hashing-with-bcrypt

> Learn how to use the Bcrypt open-source library to hash passwords in a Node.js application.

Password hashing is one of the most common tasks in a web application. Hashing generally maps data of any size to a fixed-length string by using a secure algorithm. It's a one-way function that makes it suitable for authentication.

In an [earlier article](https://attacomsian.com/blog/nodejs-encrypt-decrypt-data), I wrote about how to encrypt and decrypt strings, numbers, buffers, streams, etc. by using the Node.js built-in `crypto` module. Today, you'll learn to use another Node.js open-source library called [bcrypt](https://www.npmjs.com/package/bcrypt) for hashing passwords.

The `bcrypt` library makes it fun to hash and compare passwords in a Node.js application.

## Installation

To use the `bcrypt` library in a Node.js application, run the following command in your terminal to install it via NPM:

```bash
$ npm install bcrypt --save
```

Now, you can include it in your application:

```javascript
const bcrypt = require('bcrypt')
```

## Hashing a password

Bcrypt provides both asynchronous and synchronous password hashing methods. The asynchronous mode is recommended because hashing is a CPU-intensive task. 

The synchronous approach will block the event loop and prevent your application from handling any other incoming requests or events. The asynchronous version uses a thread pool that does not stop the main event loop.

### Asynchronous Hashing

The `bcrypt.hash()` function takes the plain password and salt as input and returns a hashed string. Let us write a simple function:

```javascript
const hashPassword = async (password, saltRounds = 10) => {
  try {
    // Generate a salt
    const salt = await bcrypt.genSalt(saltRounds)

    // Hash password
    return await bcrypt.hash(password, salt)
  } catch (error) {
    console.log(error)
  }

  // Return null if error
  return null
}
```

As you can see above, we first generated a salt with `bcrypt.genSalt()` and later invoked the `bcrypt.hash()` method to create a hashed string. 

The first step is optional. You can directly pass the number of salt rounds to the `bcrypt.hash()` method to achieve the same end result:

```javascript
const hash = await bcrypt.hash(password, saltRounds)
```

Now, whenever required, just call the above method to hash a password and store it in a database:

```javascript
;(async () => {
  const hash = await hashPassword('123456')
  // $2b$10$5ysgXZUJi7MkJWhEhFcZTObGe18G1G.0rnXkewEtXq6ebVx1qpjYW

  // TODO: store hash in a database
})()
```

Bcrypt also supports traditional callbacks and [JavaScript promises](https://attacomsian.com/blog/promises-javascript). I prefer to use [async-await syntax](https://attacomsian.com/blog/async-await-javascript) because it is clean and easier to understand.

### Synchronous Hashing

If you prefer to use the synchronous approach instead, just use the following code:

```javascript
// Generate Salt
const salt = bcrypt.genSaltSync(10)

// Hash Password
const hash = bcrypt.hashSync('123456', salt)

console.log(hash)
// $2b$10$Wdj1lOudt3JXEc6TBI2C6.Wafuv33FRdv9jRd9qtVdPYWmKmbtiTm
```

You can also auto-generate the salt and hash the password in the same function call:

```javascript
const hash = bcrypt.hashSync('123456', 10)
```

### Salt Rounds

The `saltRounds` parameter is critical when you hash a password with Bcrypt. It defines the number of rounds the library should go through to give you a secure hash. Bcrypt also uses this value to go through `2^rounds` processing iterations.

The higher the salt rounds, the more time it will take to generate a secure hash. On a typical 2GHz core, you can [roughly expect](https://www.npmjs.com/package/bcrypt#a-note-on-rounds):

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

## Comparing passwords

Now, if you want to compare the password entered by the user with the previously stored hashed password, just use the `bcrypt.compare()` method. Let us write a function that verifies if the password entered by the user is valid or not:

```javascript
const comparePassword = async (password, hash) => {
  try {
    // Compare password
    return await bcrypt.compare(password, hash)
  } catch (error) {
    console.log(error)
  }

  // Return false if error
  return false
}
```

The following example demonstrates how you can call the above method to validate a password entered by the user:

```javascript
;(async () => {
  // Hash fetched from DB
  const hash = `$2b$10$5ysgXZUJi7MkJWhEhFcZTObGe18G1G.0rnXkewEtXq6ebVx1qpjYW`

  // Check if the password is correct
  const isValidPass = await comparePassword('123456', hash)

  // Print validation status
  console.log(`Password is ${!isValidPass ? 'not' : ''} valid!`)
  // => Password is valid!
})()
```

Bcrypt also provides the `compareSync()` method to perform the comparison synchronously:

```javascript
const isValidPass = bcrypt.compareSync(password, hash)
```

## Conclusion

That's all about hashing passwords using Bcrypt in a Node.js application. You've just learned how to hash and verify passwords with Node.js and Bcrypt.

Take a look at [Bcrypt docs](https://www.npmjs.com/package/bcrypt#api) to learn more about all the available options and API methods.
