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

Argon2 Password Hashing

security OWASP A2:2021 PHP 7.2+ Intermediate
debt(d5/e3/b3/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches it' (d5). The term's detection_hints list phpstan and semgrep as tools that can detect usage of PASSWORD_BCRYPT when PASSWORD_ARGON2ID is available, or low bcrypt cost factors. These are specialist SAST/static-analysis tools rather than default linters, so d5 fits well. A default PHP linter won't flag this; you need configured semgrep rules or phpstan extensions.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is essentially swapping PASSWORD_BCRYPT or PASSWORD_DEFAULT to PASSWORD_ARGON2ID in password_hash() calls — a one-line change per call site. However, common_mistakes include setting memory cost too low and using === instead of password_verify(), which may require touching multiple call sites across the codebase. The core fix is near e1 but addressing all related mistakes (memory cost tuning, ensuring password_verify usage, verifying hash storage format) pushes it to e3.

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

Closest to 'localised tax' (b3). The choice of password hashing algorithm is typically confined to the authentication layer — one component (user registration/login) pays the cost, and the rest of the codebase is unaffected. It applies to web and cli contexts but the actual code surface is narrow. It doesn't define the system's shape or impose a persistent productivity tax beyond the auth module.

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

Closest to 'notable trap' (t5). The misconception field states that developers believe 'any Argon2 variant is equally secure,' when in fact Argon2i is vulnerable to GPU cracking and Argon2d to side-channel attacks — only Argon2id combines both protections. Additionally, common mistakes like assuming PASSWORD_DEFAULT selects Argon2 on older PHP, setting memory cost too low (negating the entire benefit), and using === instead of password_verify() represent documented gotchas that most devs eventually learn but are genuinely surprising at first encounter.

About DEBT scoring →

Also Known As

Argon2id Argon2i memory-hard hashing

TL;DR

The Password Hashing Competition winner (2015) — a memory-hard algorithm that resists GPU and ASIC brute-force attacks better than bcrypt.

Explanation

Argon2 comes in three variants: Argon2d (GPU resistance), Argon2i (side-channel resistance), and Argon2id (recommended — hybrid of both). It has three tunable cost parameters: memory (in KiB), time (iterations), and parallelism (threads), making it far more flexible than bcrypt's single cost factor. In PHP 7.2+, use PASSWORD_ARGON2ID with password_hash(). The OWASP recommendation is Argon2id with at least 19 MiB memory, 2 iterations, and 1 parallelism thread as a minimum configuration.

Diagram

flowchart TD
    PASSWORD2[Password] --> PARAMS[Configure params<br/>memory_cost time_cost threads]
    PARAMS --> FILL[Fill memory with pseudo-random data<br/>memory-hard - GPU resistant]
    FILL --> DERIVE[Derive hash output]
    DERIVE --> ENCODED[Encoded string<br/>algo + params + salt + hash]
    subgraph vs_bcrypt
        ARG_WIN[Argon2id wins<br/>memory-hard - defeats GPU farms<br/>configurable all dimensions<br/>Winner of PHC 2015]
        BC_WEAK[bcrypt weakness<br/>max 72 chars truncated<br/>not memory-hard]
    end
    subgraph PHP
        PHP_HASH[PASSWORD_ARGON2ID<br/>password_hash built-in]
    end
style FILL fill:#6e40c9,color:#fff
style ARG_WIN fill:#238636,color:#fff
style BC_WEAK fill:#f85149,color:#fff
style PHP_HASH fill:#1f6feb,color:#fff

Common Misconception

Any Argon2 variant is equally secure. Argon2i is vulnerable to GPU cracking; Argon2d is vulnerable to side-channel attacks. Use Argon2id for password hashing — it combines protections from both.

Why It Matters

Argon2 is deliberately memory-hard, meaning GPU and ASIC attacks that crack bcrypt in seconds still take days — it sets the current gold standard for password storage.

Common Mistakes

  • Using PASSWORD_DEFAULT in password_hash() and not knowing it may not select Argon2 on older PHP.
  • Setting memory cost too low (less than 65536 KB) and negating the memory-hardness benefit.
  • Comparing hashes with === instead of password_verify(), which breaks timing-safe comparison.
  • Storing the raw hash output without the algorithm prefix, losing upgrade path information.

Code Examples

✗ Vulnerable
password_hash($pwd, PASSWORD_BCRYPT); // bcrypt fine but Argon2id preferred
✓ Fixed
password_hash($pwd, PASSWORD_ARGON2ID, ['memory_cost' => 65536, 'time_cost' => 4, 'threads' => 1]);

Added 15 Mar 2026
Edited 22 Mar 2026
Views 69
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 2 pings M 0 pings T 0 pings W 2 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S
No pings yesterday
ChatGPT 14 Perplexity 14 Google 6 Amazonbot 6 Ahrefs 2 Unknown AI 2 SEMrush 1 Qwen 1
crawler 45 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Low
⚡ Quick Fix
Use PASSWORD_ARGON2ID as the algorithm in password_hash() — it is memory-hard making GPU brute force impractical even with hardware attackers
📦 Applies To
PHP 7.2+ web cli
🔗 Prerequisites
🔍 Detection Hints
password_hash with PASSWORD_BCRYPT when PASSWORD_ARGON2ID is available; bcrypt cost factor <12
Auto-detectable: ✓ Yes phpstan semgrep
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✓ Auto-fixable Fix: Low Context: Line Tests: Update
CWE-916

✓ schema.org compliant