Password Hashing
Overview
If you store user passwords in Plain Text (e.g., password123) in your database, and your server gets hacked, the hacker now has the passwords for thousands of users (who likely re-use that password on their bank accounts). This is criminally negligent. Passwords must be Hashed. A Hash is a one-way cryptographic math algorithm. It turns password123 into $2b$10$wI8.... It is mathematically impossible to reverse a Hash back into the original password.
Syntax
// Using 'bcrypt', the global standard for password hashing
const bcrypt = require('bcrypt');
// --- 1. REGISTRATION (Hashing the password before saving) ---
app.post('/register', async (req, res) => {
const plainTextPassword = req.body.password; // 'mypassword'
// The Salt Rounds (10) determines how mathematically difficult the hash is.
// 10 rounds takes ~100ms. It protects against brute-force attacks!
const saltRounds = 10;
const hashedPassword = await bcrypt.hash(plainTextPassword, saltRounds);
// Save THIS to the database! ($2b$10$wI8J7yH...)
await db.query('INSERT INTO users (pass) VALUES ($1)', [hashedPassword]);
});
// --- 2. LOGIN (Comparing without ever decrypting) ---
app.post('/login', async (req, res) => {
const userInput = req.body.password; // 'mypassword'
const hashFromDatabase = '$2b$10$wI8J7yH...';
// Bcrypt hashes the userInput, and checks if it mathematically
// matches the hash in the database!
const isMatch = await bcrypt.compare(userInput, hashFromDatabase);
if (isMatch) res.send("Welcome!");
else res.status(401).send("Invalid password");
});Common Pitfalls
- Using standard algorithms like MD5 or SHA-256 for passwords. These algorithms are incredibly fast (designed to check file integrity). A hacker using modern GPUs can guess 100 Billion MD5 hashes per second, instantly cracking your database. You MUST use 'Slow Hashing' algorithms specifically designed for passwords, like
BcryptorArgon2. - Using
bcrypt.hashSync(). The synchronous version of Bcrypt blocks the Node.js V8 Engine for 100+ milliseconds while it does the intense math. If 10 users login at once, your server freezes for 1 full second. Always use theawait bcrypt.hash()asynchronous version to offload the math to the libuv thread pool.
Interview Questions
A Salt is a random string of characters appended to the password BEFORE it is hashed. If two users have the exact same password ('12345'), without a salt, their hashes would be identical. A hacker could crack one and instantly know the other. A Salt guarantees that identical passwords generate completely unique hashes.
Real-World Example
Why we never explicitly tell the user whether the email or the password was wrong during login.
// BAD: Allows hackers to enumerate and guess valid emails in your database
if (!user) return res.status(401).send("Email not found");
if (!isMatch) return res.status(401).send("Incorrect password");
// GOOD: Generic response protects against User Enumeration attacks!
if (!user || !isMatch) {
return res.status(401).send("Invalid email or password");
}Check Your Knowledge
Test your understanding of Password Hashing with these quick questions.