Skip to content
Security 8 min read

Bcrypt Password Hashing: Why It's the Gold Standard

Learn why bcrypt is the recommended algorithm for password hashing, how the cost factor and salting work, how to implement it in Node.js and Python, and when to use Argon2 instead.

ToolsVito Team

Why You Can't Just Use SHA-256 for Passwords

General-purpose hash functions like SHA-256 are optimized for speed. A modern GPU can compute over 10 billion SHA-256 hashes per second. If an attacker obtains your hashed password database and knows the algorithm, they can test billions of candidate passwords per second using rainbow tables or brute force.

Password hashing algorithms are designed to be deliberately slow and memory-intensive, making brute-force attacks impractical even with specialized hardware.

How Bcrypt Works

Bcrypt was designed by Niels Provos and David Mazières in 1999 based on the Blowfish cipher. Its key properties:

  1. Automatic salting: Bcrypt generates a random 128-bit salt for every password. This means two identical passwords produce completely different hashes, defeating rainbow table attacks.
  2. Adjustable cost factor: The rounds parameter (typically 10–14) determines the number of iterations. Each increment doubles the computation time.
  3. Self-contained hash string: The bcrypt output includes the algorithm version, cost factor, salt, and hash — everything needed for verification.

Anatomy of a Bcrypt Hash

$2b$12$EXAMPLESALTabcdefghijk.hashhashhashhashhashhashhashhash
 │   │  │                    │
 │   │  └─ 22-char salt      └─ 31-char hash
 │   └─ cost factor (2^12 = 4096 iterations)
 └─ algorithm version (2b)

Bcrypt in Node.js

import bcrypt from "bcrypt";

// Hash a password
const saltRounds = 12;
const hash = await bcrypt.hash("mySecurePassword!", saltRounds);
// "$2b$12$..."

// Verify a password
const isValid = await bcrypt.compare("mySecurePassword!", hash);
// true

Use bcrypt (C++ bindings, faster) or bcryptjs (pure JS, no native deps). Both expose the same API.

Bcrypt in Python

import bcrypt

# Hash
password = b"mySecurePassword!"
hashed = bcrypt.hashpw(password, bcrypt.gensalt(rounds=12))

# Verify
bcrypt.checkpw(password, hashed)  # True

Choosing the Right Cost Factor

The cost factor should be set so that hashing takes approximately 100–250ms on your production hardware. This is slow enough to deter brute-force but fast enough to not frustrate users logging in:

// Benchmark on your server
const start = Date.now();
await bcrypt.hash("test", 12);
console.log(Date.now() - start, "ms");

As hardware gets faster, increase the cost factor in your application and re-hash passwords on next login. Industry recommendation as of 2024: cost factor 12 or higher.

Common Mistakes

  • Pre-hashing before bcrypt: Running sha256(password) before bcrypt can actually weaken security because bcrypt truncates input at 72 bytes; SHA-256 output is 64 bytes, reducing the effective input space.
  • Synchronous API in web servers: bcrypt.hashSync() blocks the Node.js event loop. Always use the async API.
  • Cost factor too low: Cost factor 10 was fine in 2012; by 2024 GPUs have made it too fast. Use 12+.
  • Storing plain passwords anywhere: Never log passwords, never store them in analytics, never send them to third parties.

Bcrypt vs Argon2 vs PBKDF2

  • Bcrypt: Battle-tested since 1999, 72-byte input limit, not memory-hard.
  • Argon2: Winner of the Password Hashing Competition (2015), memory-hard (resists GPU/ASIC attacks), configurable memory and parallelism. The current best practice recommendation.
  • PBKDF2: FIPS-approved, built into many standard libraries (including Node.js crypto), but not memory-hard.

If you're starting a new project, prefer Argon2id. If you have an existing bcrypt implementation, it's not worth migrating — bcrypt at cost 12+ is still adequately secure.

Hash & Verify Passwords in the Browser

Use ToolsVito's Bcrypt Tool to hash and verify passwords directly in your browser — useful for testing, debugging, and one-off checks.

Try it now — free, runs in your browser

Bcrypt Hash & Verify

Hash & check passwords