bcrypt
debt(d5/e2/b3/t6)
Closest to 'specialist tool catches' (d5), semgrep/phpstan rules can flag md5/sha1 in auth contexts, but the 72-byte truncation and low cost factor are silent in production.
Closest to 'one-line patch' (e1) with slight bump toward e3, swapping md5() for password_hash($pass, PASSWORD_BCRYPT) is mostly a one-line fix but may require DB column widening to 60 chars and rehashing on next login.
Closest to 'localised tax' (b3), password hashing is concentrated in the auth component; the choice affects login/registration flows but doesn't shape the rest of the codebase.
Closest to 'serious trap' (t7), the misconception that bcrypt is universally safe hides the 72-byte silent truncation — two long passwords differing past byte 72 hash identically, contradicting how developers expect a hash to behave.
Also Known As
TL;DR
Explanation
bcrypt incorporates a cost factor (work factor) that determines how many iterations the algorithm runs. Increasing the cost doubles the computation time per hash — making brute-force attacks proportionally harder as hardware improves. A cost of 12 is a reasonable 2026 default. bcrypt also salts automatically, so two hashes of the same password are always different. In PHP, use password_hash($pass, PASSWORD_BCRYPT, ['cost' => 12]) and password_verify() to check.
Diagram
flowchart TD
PASSWORD[Plain text password] --> SALT[Generate random salt<br/>22 chars base64]
SALT --> COST[Apply cost factor<br/>default 12 = 2^12 iterations]
COST --> HASH2[bcrypt hash<br/>60 chars total]
HASH2 --> STORE2[(Store in DB)]
subgraph Verify
INPUT[Login attempt] --> VER[password_verify<br/>extracts salt + cost<br/>rehashes and compares]
VER -->|match| OK[Authenticated]
VER -->|no match| FAIL2[Rejected]
end
subgraph Cost_Factor
C10[Cost 10 = 100ms]
C12[Cost 12 = 400ms]
C14[Cost 14 = 1600ms]
C10 --> C12 --> C14
end
style HASH2 fill:#6e40c9,color:#fff
style OK fill:#238636,color:#fff
style FAIL2 fill:#f85149,color:#fff
style C12 fill:#238636,color:#fff
Common Misconception
Why It Matters
Common Mistakes
- Using MD5, SHA-1, or SHA-256 for passwords — these are fast hashes, not password hashing algorithms.
- Setting the cost factor too low (below 10) — higher cost dramatically increases brute-force time.
- Storing bcrypt hashes in columns shorter than 60 characters — the full hash will be truncated.
- Hashing passwords before bcrypt (e.g. md5($pass)) — pre-hashing can reduce the effective input space.
Code Examples
// NEVER hash passwords with md5, sha1, sha256 — they're fast (crackable)
$hash = md5($password);
$hash = sha256($password);
$hash = sha256($salt . $password);
// PHP built-in — uses bcrypt by default (cost=10), upgradeable
$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]);
// Verify (timing-safe)
if (password_verify($input, $hash)) { /* authenticated */ }
// Check if rehash needed (after cost increase)
if (password_needs_rehash($hash, PASSWORD_BCRYPT, ['cost' => 12])) {
$hash = password_hash($input, PASSWORD_BCRYPT, ['cost' => 12]);
// save new hash
}