SuperAPI AI Directory

bcrypt

General & other

View repository

Updated 10-15 21:49

About this skill

Bcrypt

Bcrypt is a password-hashing function designed to be slow, protecting against brute-force attacks. It incorporates a salt to protect against rainbow table attacks.

When to Use

  • User Password Hashing: Hashing user passwords securely before storing them in database tables.
  • Authentication Verification: Verifying incoming plaintext passwords against hashed records during login attempts.
  • Legacy Credential Protection: Maintaining established authentication backends using the proven, battle-tested bcrypt algorithm.
  • Adaptive Cost Factor Tuning: Adjusting computational work factors over time to counter advances in hardware cracking performance.

Quick Start

import bcrypt from "bcrypt";

const saltRounds = 10;
const myPlaintextPassword = "s0m3password";

// Hashing const hash = await bcrypt.hash(myPlaintextPassword, saltRounds); // Store 'hash' in DB: $2b$10$EpIxT98h....

// Verifying const match = await bcrypt.compare("s0m3password", hash); if (match) { // Login successful }


## Core Concepts

### The Modular Crypt Format ($2b$ Cost $ Salt + Hash)

Bcrypt outputs a standardized 60-character string encoding the algorithm revision, work factor, 128-bit salt, and 184-bit hash:

```text
$2b$12$e8Y5W5t2KqfO.oXWf1NfTeu4GZ7hJ2xM.wKzV8L8T7p6Q9r8S1t2u
 ── ── ────────────────────── ──────────────────────────────
 │  │             │                         │
 │  │             │                         └── 31-character checksum/hash
 │  │             └──────────────────────────── 22-character base64 salt
 │  └────────────────────────────────────────── Work Factor (2^12 = 4,096 iterations)
 └───────────────────────────────────────────── Algorithm Identifier (2b)

Salting & Adaptive Work Factor

Salting prevents rainbow table attacks; the cost factor dictates exponential computation time:

import bcrypt from "bcrypt";

// Cost factor of 12 takes ~200-300ms on modern server CPUs
const SALT_ROUNDS = 12;

export async function hashPassword(plainText: string): Promise<string> {
  const salt = await bcrypt.genSalt(SALT_ROUNDS);
  return await bcrypt.hash(plainText, salt);
}

Constant-Time Password Verification

Prevents side-channel timing attacks by performing comparisons in constant time:

export async function verifyCredentials(
  plainText: string,
  hash: string,
): Promise<boolean> {
  // Constant-time execution ensures identical response latency regardless of match index
  return await bcrypt.compare(plainText, hash);
}

Common Patterns

Password Hashing and Constant-Time Verification

Problem: Storing plaintext or unsalted hashes allows rainbow table and timing-attack exploitation.

Solution: Hash with optimal cost factor (12-14 rounds) and verify asynchronously:

import bcrypt from "bcrypt";

const SALT_ROUNDS = 12;

export async function hashPassword(plainPassword) {
  return await bcrypt.hash(plainPassword, SALT_ROUNDS);
}

export async function verifyPassword(plainPassword, hashedPassword) {
  return await bcrypt.compare(plainPassword, hashedPassword);
}

Best Practices

Do:

  • Use a Work Factor of at least 12: Benchmark hashing time on production servers aiming for 250ms per hash.
  • Re-Hash Passwords on Login: Check if legacy hashes have lower cost factors (bcrypt.getRounds(hash) < 12) and upgrade them dynamically upon successful login.
  • Handle the 72-Byte Truncation Limit: Pre-hash passwords with SHA-256 before bcrypt if users are permitted to submit arbitrarily long passphrases.
  • Offload Hashing from Event Loops: Always use asynchronous bcrypt.hash() rather than blocking bcrypt.hashSync().

Don't:

  • Use MD5, SHA-1, or plain SHA-256 for passwords: Fast general-purpose hashing functions allow billions of guesses per second on consumer GPUs.
  • Generate salts manually without cryptographically secure random sources: Use bcrypt.genSalt() which taps /dev/urandom.
  • Log or print plaintext passwords: Sanitize incoming request bodies in logging middleware before persisting access logs.

Troubleshooting

Error Cause Solution
Illegal arguments: undefined, string Plaintext password or hash passed as null/undefined to compare. Validate that both arguments are non-empty strings before calling bcrypt.compare.
High CPU usage / slow responses Salt rounds set too high (>15) blocking event loop. Benchmark work factor; recommended value is 12 (approx ~250ms).
data and hash arguments required Parameter ordering reversed in compare function. Use bcrypt.compare(candidatePassword, storedHash).

References