liveBook · Manning

Bcrypt

As explained in Grokking Web Application Security

bcrypt is an adaptive password-hashing function designed to make password guessing computationally expensive.

bcrypt is a password-hashing choice for applications that must verify passwords without storing them in plain text. It turns a supplied password into a hash, then checks a later login by recalculating and comparing that value. Its deliberate computational cost makes large-scale password guessing more expensive than with older weak choices such as MD5. section 3.8 section 8.12

A hash alone is not enough protection against precomputed password guesses. Generate a different salt for every password and store it with that password’s hash. Add a pepper held outside the database, such as in configuration, so a database leak does not give an attacker every input needed to reproduce hashes. section 8.12

Use bcrypt as part of a practical credential-handling flow:

  • Generate a fresh salt when creating or changing each password. section 8.12
  • Hash the password with bcrypt and save the resulting hash and salt rather than the password itself. section 3.8 section 8.12
  • Keep a pepper outside the database and include it consistently when hashing and checking passwords. section 8.12
  • On login, hash the supplied password with the same inputs and compare the recalculated value with the stored hash. section 3.8 section 8.12
  • Raise bcrypt’s configured cycle count as available computing power grows, while pairing password storage with rate limiting, CAPTCHA, and MFA against online guessing. section 8.12 section 8.17

Password check with a salt and pepper

A Ruby flow generates a bcrypt salt, reads a pepper from an environment variable, and hashes the combined values. To verify a login, it repeats the same calculation and compares the result with the saved hash. The salt remains available with the hash; the pepper remains outside the database. section 8.12

require 'bcrypt'

def hash_password(password)
 salt   = BCrypt::Engine.generate_salt
 pepper = ENV['PEPPER']
 hashed_password = BCrypt::Engine.hash_secret(
   pepper + password + salt, salt)
 return [hashed_password, salt]
end

def check_password(password, hashed_password, salt)
 pepper = ENV['PEPPER']
 recalculated_hash = BCrypt::Engine.hash_secret(
   pepper + password + salt, salt)

 return hashed_password == recalculated_hash
end

Inspect a compact Ruby implementation of hash_password and check_password, including salt generation, environment-based pepper retrieval, and hash comparison. section 8.12

bcrypt reduces the damage of a password-hash leak, but it does not make weak or reused passwords safe. Favor long, complex passwords, protect login and reset endpoints from brute-force attempts, and avoid account-existence leaks by calculating a supplied-password hash even when no matching account exists. section 3.8 section 8.17

How Grokking Web Application Security covers it

How deep it goes
Explains hashing, configurable cycles, salts, peppers, and Ruby hash-and-compare functions without detailing bcrypt internals.
Examples
Demonstrates Ruby bcrypt code that generates salts, hashes passwords, reads an environment pepper, and compares recalculated hashes.
What it assumes
Introduces bcrypt from zero through password storage and login verification rather than assuming security-specialist knowledge.
What you can do after
Apply it via BCrypt to hash and verify passwords with per-password salts and a separately stored pepper.
How it connects
Connects password hashing with salts, peppers, password cracking, rainbow tables, rate limiting, CAPTCHA, and MFA.

Also explained in

Compare how 3 books explain bcrypt →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Grokking Web Application Security. The section links point to the parts of the book it draws on.