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

Key Derivation Functions

cryptography PHP 5.5+ Advanced

Also Known As

PBKDF2 bcrypt scrypt Argon2 password hashing KDF

TL;DR

KDFs (PBKDF2, bcrypt, scrypt, Argon2) derive a cryptographic key from a password by being intentionally slow — making brute-force attacks computationally infeasible.

Explanation

Passwords must not be stored directly — a KDF transforms a password into a hash that cannot be reversed, and is deliberately slow to compute. bcrypt: adaptive cost factor, max 72 chars, PHP's password_hash() default. scrypt: memory-hard (GPU/ASIC resistant) — good for application-level KDFs. Argon2 (Argon2id recommended): winner of Password Hashing Competition, configurable time+memory+parallelism — PHP password_hash() with PASSWORD_ARGON2ID. PBKDF2: NIST-approved, widely supported, less memory-hard than Argon2/scrypt. Never use MD5/SHA (fast — trivially brute-forced).

Common Misconception

SHA-256 is a strong password hash — SHA-256 is a fast hash designed for integrity checking; it can hash billions of passwords per second on a GPU — use Argon2id or bcrypt instead.

Why It Matters

A leaked database with SHA-256 hashed passwords is cracked within hours with a GPU; the same database with Argon2id hashes would take centuries — the algorithm choice is the critical factor.

Common Mistakes

  • MD5 or SHA-1 for passwords — deprecated and trivially cracked; any data breach is catastrophic.
  • bcrypt with passwords > 72 characters — bcrypt silently truncates; use Argon2id for long passwords.
  • Low cost/iteration count — makes hashing fast and brute force feasible; use the highest cost your server tolerates.
  • Not using PHP's password_verify() — manual comparison with == is vulnerable to timing attacks; password_verify() uses constant-time comparison.

Code Examples

✗ Vulnerable
// MD5 password hash — trivially cracked:
$hash = md5($password);          // Cracked in seconds with GPU
$hash = sha256($password);       // Fast — millions/sec on GPU
$hash = md5(md5($password));     // Still fast — do not use

// Manual comparison — timing attack:
if ($storedHash === md5($password)) { /* login */ }
✓ Fixed
// Argon2id — slow, memory-hard, PHP native:
$hash = password_hash($password, PASSWORD_ARGON2ID, [
    'memory_cost' => 65536,  // 64 MB
    'time_cost'   => 4,      // 4 iterations
    'threads'     => 2,
]);

// Verify with constant-time comparison:
if (password_verify($password, $hash)) {
    // Login — rehash if needs_rehash():
    if (password_needs_rehash($hash, PASSWORD_ARGON2ID)) {
        $newHash = password_hash($password, PASSWORD_ARGON2ID);
        updateStoredHash($userId, $newHash);
    }
}

Added 15 Mar 2026
Edited 22 Mar 2026
Views 40
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 1 ping W 1 ping T 1 ping F 0 pings S 1 ping S 1 ping M 1 ping T 0 pings W 1 ping T
No pings yesterday
Amazonbot 16 Perplexity 9 Google 6 SEMrush 3 Ahrefs 2 Majestic 1 Unknown AI 1
crawler 34 crawler_json 4
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Medium
⚡ Quick Fix
Use Argon2id for passwords (password_hash()), PBKDF2 for key derivation from passphrases (hash_pbkdf2()), and HKDF for expanding cryptographic keys — never use a plain hash as a key derivation function
📦 Applies To
PHP 5.5+ web cli
🔗 Prerequisites
🔍 Detection Hints
md5() sha1() sha256() used directly for password storage; hash('sha256', $password) as key without PBKDF2 or Argon2; no iterations/cost factor
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line Tests: Update
CWE-916 CWE-759 CWE-760

✓ schema.org compliant