Skip to main content

Password Hashing with Bcrypt

In the previous lesson, we learned about the importance of authentication and the concept of credentials. Now, let's dive into one of the most critical aspects of authentication: Password Hashing.

Imagine a user signs up for your site with the password secret123.

  • The Wrong Way: Saving secret123 directly in MongoDB.
  • The Master Way: Saving $2b$10$nOUIs5kJ7naTuTFkBy1veuK...

If a hacker steals the "Master Way" data, they have no idea what the real password is.

1. What is Hashing?

A Hash Function is a one-way mathematical algorithm. You put data in, and you get a fixed-length string out.

Key Properties of Hashing:

  1. One-Way: You can turn a password into a hash, but you cannot turn a hash back into a password.
  2. Deterministic: The same password will always produce the same hash (unless we add "Salt").
  3. Fast but Secure: It needs to be fast enough for users, but slow enough to stop hackers from trying billions of combinations.

2. What is "Salting"?

If two users use the same password (like 123456), they would normally have the same hash. A hacker could use a "Rainbow Table" (a list of pre-calculated hashes) to figure them out instantly.

Salting is adding random characters to the password before hashing it.

  • Password: password123
  • Salt: ax79!z
  • Result to be hashed: password123ax79!z

This ensures that even if two users have the same password, their hashes will look completely different.

3. Using Bcrypt in Node.js

Bcrypt is the gold standard library for hashing. It handles both the salt and the hash in one easy process.

Installation

npm install bcrypt

Hashing a Password (Signup)

When a user registers, you hash their password before saving it to the database.

hashing.js
const bcrypt = require('bcrypt');

const signup = async (password) => {
const saltRounds = 10; // The "cost" of hashing (higher = more secure but slower)

const hashedPassword = await bcrypt.hash(password, saltRounds);

console.log('Original:', password);
console.log('Hashed:', hashedPassword);

// Save hashedPassword to your Database!
};

Verifying a Password (Login)

Since you can't "unhash" a password, how do you check if a user entered the right one? You hash the attempted password and compare it to the one in the database.

login.js
const login = async (enteredPassword, storedHash) => {
// Bcrypt handles the salt comparison automatically
const isMatch = await bcrypt.compare(enteredPassword, storedHash);

if (isMatch) {
console.log("✅ Access Granted!");
} else {
console.log("❌ Incorrect Password!");
}
};

4. Why 10 Salt Rounds?

The saltRounds parameter determines how much processing power is required to calculate the hash.

  • If it's too low (e.g., 1), it's too fast and easy to hack.
  • If it's too high (e.g., 20), your server will take 10 seconds to log someone in!
  • 10-12 rounds is currently the "sweet spot" for modern servers.

Practice: The "Master" Security Script

  1. Create a small Node script.
  2. Hash three different passwords: apple, apple1, and apple (again).
  3. Observe how the two apple hashes are different because of the random salt.
  4. Try to "log in" by comparing a wrong password to one of your hashes.
Don't Forget!

Always await your bcrypt functions. Hashing is a CPU-intensive task, and if you don't handle the promises correctly, your code might try to save an empty password to the database!