← Home ← Codex ← DEBT
Browse by Category
+ added · updated 7d
← Back to glossary

password_hash() — Native Bcrypt (PHP 5.5)

PHP PHP 5.5+ Beginner
debt(d5/e3/b3/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The detection_hints list phpcs, semgrep, and phpstan — all specialist/SAST tools. The code_pattern 'md5.*password|sha1.*password' means automated detection is possible but requires configuring these tools; it won't be caught by a basic compiler or default linter pass.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a pattern replacement — swap MD5/SHA1 calls with password_hash(PASSWORD_ARGON2ID) and add password_needs_rehash() on login. This touches authentication code but is a recognisable, repeatable substitution within one component rather than a cross-cutting architectural change.

b3 Burden Structural debt — long-term weight of choosing wrong

Closest to 'localised tax' (b3). Password hashing logic is typically concentrated in one authentication component (registration, login, password reset). Once corrected, the fix doesn't impose an ongoing tax on unrelated parts of the codebase — applies_to is web/cli but the actual usage site is narrow.

t7 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'serious trap' (t7). The misconception is explicit: developers believe 'MD5 with a salt is secure for passwords,' contradicting the actual security model. MD5/SHA1 are fast hashes used legitimately for checksums elsewhere, so a competent developer who hasn't studied password-specific security will confidently reach for them — a pattern that directly contradicts how hashing should work for passwords.

About DEBT scoring →

TL;DR

PHP 5.5 added password_hash() and password_verify() — the only correct way to hash and verify passwords. Never use MD5, SHA1, or unsalted hashes.

Explanation

password_hash($password, PASSWORD_BCRYPT) generates a bcrypt hash with automatic salting. password_verify($input, $hash) verifies. PASSWORD_DEFAULT currently means bcrypt but may change — store the full hash string including algorithm prefix. PHP 7.2+ adds PASSWORD_ARGON2I. PHP 7.3+ adds PASSWORD_ARGON2ID (preferred). password_needs_rehash($hash, PASSWORD_DEFAULT) checks if rehashing is needed after algorithm upgrades. Never: MD5/SHA1 for passwords, unsalted hashes, static salts, or reversible encryption for passwords.

Common Misconception

MD5 with a salt is secure for passwords — MD5 is a fast hash designed for checksums, not passwords. Bcrypt/Argon2 are specifically designed to be slow for brute-force resistance.

Why It Matters

Password storage is the single most critical security function in most web apps — one wrong choice exposes every user's credentials in a breach.

Common Mistakes

  • Using MD5($password) or SHA1($password) — crackable in seconds with rainbow tables.
  • Not using password_needs_rehash() during login — fails to upgrade old hashes.
  • Truncating passwords before hashing — bcrypt has 72-byte limit in older implementations.

Code Examples

✗ Vulnerable
$hash = md5($password); // Crackable instantly
$hash = md5($password . $salt); // Still fast, GPU-crackable
$hash = sha256($password); // Wrong tool — designed for speed
✓ Fixed
// Hash on registration:
$hash = password_hash($password, PASSWORD_ARGON2ID);

// Verify on login:
if (password_verify($inputPassword, $storedHash)) {
    // Upgrade hash if algorithm changed:
    if (password_needs_rehash($storedHash, PASSWORD_ARGON2ID)) {
        $newHash = password_hash($inputPassword, PASSWORD_ARGON2ID);
        // Store $newHash
    }
}

Added 23 Mar 2026
Views 221
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
1 ping T 1 ping W 2 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 1 ping S 1 ping S 1 ping M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 4 pings F 1 ping S 1 ping S 0 pings M 4 pings T 0 pings W
No pings yet today
PetalBot 2 Google 2
ChatGPT 114 Perplexity 31 Google 14 Amazonbot 9 Unknown AI 4 Scrapy 4 Ahrefs 3 SEMrush 3 PetalBot 3 Claude 1 Bing 1 Meta AI 1 Majestic 1
crawler 182 crawler_json 6 pre-tracking 1
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Medium
⚡ Quick Fix
Replace all MD5/SHA1 password hashing with password_hash(PASSWORD_ARGON2ID). Add password_needs_rehash() check on login. Never store plaintext or reversible passwords.
📦 Applies To
PHP 5.5+ web cli
🔗 Prerequisites
🔍 Detection Hints
md5.*password|sha1.*password|sha256.*password
Auto-detectable: ✓ Yes phpcs semgrep phpstan
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Medium Context: Function Tests: Update
CWE-916 CWE-328 CWE-759


✓ schema.org compliant