Key Derivation Functions
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);
}
}
Tags
🤝 Adopt this term
£79/year · your link shown here
Added
15 Mar 2026
Edited
22 Mar 2026
Views
40
🤖 AI Guestbook educational data only
|
|
Last 30 days
Agents 1
No pings yesterday
Amazonbot 16
Perplexity 9
Google 6
SEMrush 3
Ahrefs 2
Majestic 1
Unknown AI 1
Also referenced
How they use it
crawler 34
crawler_json 4
Related categories
⚡
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