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

Cryptography Common Mistakes

Cryptography PHP 7.1+ Intermediate
debt(d5/e5/b7/t7)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). Semgrep and Psalm (from detection_hints.tools) can detect patterns like AES-ECB mode, static IV constants, and openssl_encrypt without MAC through static analysis rules. However, these require specific rulesets configured for cryptographic anti-patterns rather than default linting.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor' (e5). While the quick_fix suggests AES-256-GCM avoids common mistakes, retrofitting existing encryption throughout a codebase requires updating all encryption/decryption call sites, migrating stored ciphertext, and ensuring consistent authenticated encryption across the system.

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

Closest to 'strong gravitational pull' (b7). Cryptographic choices in applies_to contexts (web, cli) become load-bearing infrastructure. Password hashing, token generation, and data encryption are used system-wide; a wrong choice (e.g., SHA-256 for passwords instead of Argon2id) shapes how authentication and data protection work everywhere, requiring coordinated migration to fix.

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

Closest to 'serious trap' (t7). The misconception explicitly states that developers believe 'openssl_encrypt is always sufficient' when encryption without authentication allows ciphertext modification. Using == for MAC comparison seems correct but enables timing attacks. These contradict how similar concepts work elsewhere (comparison operators, basic encryption) and the 'obvious' approach fails silently.

About DEBT scoring →

Also Known As

crypto mistakes IV reuse roll your own crypto cryptographic failure

TL;DR

IV reuse, ECB mode, rolling your own crypto, timing vulnerabilities, and SHA-256 for passwords — the most frequent implementation errors.

Explanation

Common mistakes: (1) Rolling your own crypto — use battle-tested libraries only. (2) Reusing IV/nonce in GCM — catastrophically breaks confidentiality and authentication. (3) ECB mode — identical plaintext blocks produce identical ciphertext, leaking patterns. (4) Timing-vulnerable comparison — use hash_equals() not ==. (5) SHA-256 for passwords — fast algorithm, GPU-crackable; use Argon2id. (6) No authenticated encryption — AES-CBC without MAC allows ciphertext tampering. (7) Trusting user-provided algorithm — JWT alg:none, algorithm confusion attacks.

Common Misconception

Encrypting with openssl_encrypt is always sufficient — encryption without authentication (MAC/GCM) allows attackers to modify ciphertext without detection; always use AES-GCM or add HMAC separately.

Why It Matters

Most real-world cryptographic failures are implementation mistakes — wrong mode, reused nonce, timing leaks — not mathematical attacks on strong algorithms. These mistakes are common and exploitable.

Common Mistakes

  • AES-CBC without MAC — ciphertext is malleable
  • IV/nonce reuse in GCM — recovering the auth key
  • SHA-256 for passwords — bcrypt/Argon2id is required
  • == for comparing MACs/tokens — timing attack enables brute-force

Code Examples

✗ Vulnerable
// Multiple critical mistakes:
$key = 'secret';                         // Short, non-derived key
$iv  = str_repeat('0', 16);             // Static IV — reused every time!
$enc = openssl_encrypt($data, 'AES-128-ECB', $key); // ECB mode!
// No authentication — ciphertext tamperable
if ($provided === $expected) { }        // Timing vulnerable
✓ Fixed
// Correct authenticated encryption:
$key = random_bytes(32);         // 256-bit key from CSPRNG
$iv  = random_bytes(12);         // Random 96-bit nonce per message
$tag = '';
$enc = openssl_encrypt(
    $data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag
);

// Constant-time comparison:
if (!hash_equals($expected, $provided)) {
    throw new SecurityException('Authentication failed');
}

Added 16 Mar 2026
Edited 22 Mar 2026
Views 49
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings W 2 pings T 0 pings F 0 pings S 1 ping S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 2 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 2 pings S 2 pings M 0 pings T 0 pings W
No pings yet today
No pings yesterday
Amazonbot 10 Google 4 Ahrefs 4 SEMrush 4 Scrapy 4 Perplexity 3 Unknown AI 3 PetalBot 3 Claude 2 ChatGPT 2 Meta AI 1
crawler 36 crawler_json 3 pre-tracking 1
DEV INTEL Tools & Severity
🔴 Critical ⚙ Fix effort: Medium
⚡ Quick Fix
The three most common: using ECB mode (patterns visible), reusing nonces/IVs (catastrophic), and encrypting without authentication (padding oracle) — AES-256-GCM avoids all three
📦 Applies To
PHP 7.1+ web cli
🔗 Prerequisites
🔍 Detection Hints
AES-ECB mode; static IV constant; openssl_encrypt without MAC; MD5/SHA1 for cryptographic purposes
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Low ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-327 CWE-326 CWE-330


✓ schema.org compliant