HeoLab
ToolsBlogAboutContact
HeoLab

Free developer tools with AI enhancement. Built for developers who ship.

Tools

  • JSON Formatter
  • JWT Decoder
  • Base64 Encoder
  • Timestamp Converter
  • Regex Tester
  • All Tools →

Resources

  • Blog
  • What is JSON?
  • JWT Deep Dive
  • Base64 Explained

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 HeoLab. All rights reserved.

Tools work in your browser. Zero data retention.

HomeBlogBcrypt: The Right Way to Hash Passwords in 2025
Table of Contents▾
  • The Password Hashing Problem
  • Why Not MD5 or SHA?
  • How Bcrypt Works
  • Bcrypt Hash Anatomy
  • Implementation in Node.js
  • Choosing the Right Cost Factor
  • Common Mistakes
  • Testing Bcrypt Hashes
  • Conclusion
security#bcrypt#security#passwords

Bcrypt: The Right Way to Hash Passwords in 2025

Why you should use bcrypt over MD5 and SHA for password storage, how the cost factor works, and implementation examples in Node.js.

Trong Ngo
February 22, 2026
4 min read

The Password Hashing Problem

When users create accounts, you must store something that lets you verify their password later — but not the password itself. If your database leaks, plaintext passwords would instantly compromise every account.

The solution: store a cryptographic hash of the password. But not all hashes are equal.

Why Not MD5 or SHA?

MD5 and SHA (SHA-1, SHA-256, etc.) are general-purpose hash functions designed for speed — they can hash billions of values per second on modern GPUs.

For file integrity checks, that speed is great. For passwords, it's catastrophic:

MD5 GPU throughput: ~200 billion hashes/second
SHA-256 GPU throughput: ~10 billion hashes/second
bcrypt (cost=10): ~40 hashes/second

An attacker with a dictionary of 1 billion common passwords can crack MD5-hashed passwords in under 5 seconds. With bcrypt at cost=10, that same attack takes 29 million seconds (~338 days).

How Bcrypt Works

Bcrypt was designed in 1999 by Niels Provos and David Mazières specifically for password hashing. It has three key properties:

1. Adaptive cost factor. The rounds parameter (also called the work factor or cost factor) controls how slow the hash is to compute. With each increment, the computation time doubles:

CostApproximate time (modern CPU)
10~100ms
11~200ms
12~400ms
13~800ms
14~1.6s

As hardware gets faster, you increase the cost factor to keep the computation slow.

2. Built-in salt. Bcrypt generates a random 22-character salt automatically and embeds it in the hash output. This prevents rainbow table attacks and ensures that the same password produces a different hash each time.

3. Maximum length. Bcrypt truncates input at 72 bytes. For most use cases this is fine, but be aware of it for very long passwords.

Bcrypt Hash Anatomy

A bcrypt hash looks like this:

$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy

Breaking it down:

$2a$     — algorithm version (2a, 2b, 2y are all bcrypt)
10$      — cost factor
N9qo8uLOickgx2ZMRZoMye  — 22-char salt (base64 encoded)
IjZAgcfl7p92ldGxad68LJZdL17lhWy  — 31-char hash

Implementation in Node.js

npm install bcryptjs
import bcrypt from 'bcryptjs';

// Hashing a password
async function hashPassword(password) {
  const saltRounds = 12; // Good for 2025
  return bcrypt.hash(password, saltRounds);
}

// Verifying a password
async function checkPassword(password, hash) {
  return bcrypt.compare(password, hash);
}

// Usage
const hash = await hashPassword('user-password-123');
// Store 'hash' in your database

// On login:
const isValid = await checkPassword('user-password-123', hash);
if (!isValid) throw new Error('Invalid credentials');

Choosing the Right Cost Factor

The OWASP recommendation for 2025 is cost factor 10 at minimum, with 12 as a better default if your server can handle the load. A simple rule: choose the highest cost factor that keeps login response time under 300ms on your production hardware.

// Test cost factor performance
async function benchmarkBcrypt(rounds) {
  const start = Date.now();
  await bcrypt.hash('test-password', rounds);
  return Date.now() - start;
}

// Run and adjust based on your server
for (const r of [10, 11, 12, 13]) {
  const ms = await benchmarkBcrypt(r);
  console.log(`rounds=${r}: ${ms}ms`);
}

Common Mistakes

Don't hash before hashing. Never MD5 or SHA the password before bcrypt — bcrypt's 72-byte limit combined with base64 output from MD5 can cause collisions.

Don't use sync variants in production. bcrypt.hashSync blocks the Node.js event loop. Always use the async Promise-based API.

Do compare the full hash. Never implement your own substring comparison. Always use bcrypt.compare which uses constant-time comparison to prevent timing attacks.

Testing Bcrypt Hashes

Use HeoLab's Bcrypt Generator to hash passwords and verify them against existing hashes directly in your browser — no backend required, 100% client-side.

Conclusion

Bcrypt is the battle-tested standard for password hashing. It's slow by design, includes salt automatically, and adapts to faster hardware over time. In 2025, use bcrypt (or Argon2id if you want the newest standard) and use nothing else for storing user passwords.

Try These Tools

Bcrypt Generator

Hash passwords with bcrypt and verify bcrypt hashes. Choose work factor 4–14.

Hash Generator

Generate MD5, SHA-1, SHA-256, and SHA-512 hashes from any text. Compare all algorithms side by side.

Password Generator

Generate cryptographically secure passwords with custom length, character sets, and strength analysis.

Related Articles

Base64 is Not Encryption: Security Misconceptions Explained

1 min read

The JWT Refresh Token Pattern Explained

2 min read

Top JWT Security Vulnerabilities and How to Prevent Them

2 min read

Back to Blog

Table of Contents

  • The Password Hashing Problem
  • Why Not MD5 or SHA?
  • How Bcrypt Works
  • Bcrypt Hash Anatomy
  • Implementation in Node.js
  • Choosing the Right Cost Factor
  • Common Mistakes
  • Testing Bcrypt Hashes
  • Conclusion

Related Articles

Base64 is Not Encryption: Security Misconceptions Explained

1 min read

The JWT Refresh Token Pattern Explained

2 min read

Top JWT Security Vulnerabilities and How to Prevent Them

2 min read