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

openssl_encrypt()

php PHP 7.1+ Advanced
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 semgrep and psalm as tools, and the code_pattern explicitly calls out CBC without HMAC, ECB mode, reused IVs, and missing GCM authentication tags — these are patterns that require static analysis or SAST tooling to catch; they won't surface at compile time or via a default linter.

e3 Effort Remediation debt — work required to fix once spotted

Closest to 'simple parameterised fix' (e3). The quick_fix is a direct function-call swap to AES-256-GCM with the correct parameters. However, the fix also requires updating IV generation, storing the authentication tag alongside ciphertext, and verifying the tag before decryption — slightly more than a one-liner but well within a single-component refactor.

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

Closest to 'localised tax' (b3). The applies_to scope is web and cli contexts generally, but encryption usage is typically confined to specific modules (auth, storage, transmission). Once corrected, the pattern doesn't impose ongoing costs across unrelated parts of the codebase; the burden is concentrated where encryption is used.

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

Closest to 'serious trap' (t7). The misconception field states developers believe any AES mode is equally secure, but ECB mode leaks data patterns and unauthenticated modes allow ciphertext tampering. This contradicts intuition — the function name implies 'encryption = security' but silently omits authentication and mode correctness, which contradicts how developers reason about symmetric encryption APIs in other languages and libraries.

About DEBT scoring →

Also Known As

openssl_encrypt() PHP encryption AES encryption PHP

TL;DR

PHP's OpenSSL wrapper for symmetric encryption — use AES-256-GCM for authenticated encryption.

Explanation

openssl_encrypt($data, $cipher, $key, $options, $iv, $tag) encrypts data using OpenSSL. The recommended cipher is aes-256-gcm — an authenticated encryption mode that provides both confidentiality and integrity. Always generate a random IV with random_bytes(openssl_cipher_iv_length($cipher)) per encryption, store it alongside the ciphertext, and verify the authentication tag on decryption. Never use ECB mode (no IV, identical plaintext blocks produce identical ciphertext). Never use a static IV.

Common Misconception

openssl_encrypt() with any AES mode is equally secure. AES-ECB mode encrypts identical plaintext blocks to identical ciphertext, leaking patterns. Always use AES-GCM or AES-CBC with a random IV — and AES-GCM also provides authentication, preventing ciphertext tampering.

Why It Matters

openssl_encrypt() is PHP's primary symmetric encryption function — misusing it (wrong mode, reused IV, no authentication) produces ciphertext that is malleable or fully decryptable by attackers.

Common Mistakes

  • Using ECB mode — it encrypts identical blocks identically, leaking data patterns.
  • Reusing the same IV across encryptions with the same key — breaks semantic security.
  • Not using an authenticated encryption mode (AES-256-GCM) — unauthenticated ciphertext can be tampered with.
  • Storing the IV separately from the ciphertext in an inconsistent way — use a standard format: IV prepended to ciphertext.

Code Examples

✗ Vulnerable
// ECB mode + reused IV — insecure:
$encrypted = openssl_encrypt($data, 'AES-256-ECB', $key); // No IV, pattern-leaking

// Correct — GCM with random IV:
$iv = random_bytes(12);
$tag = '';
$encrypted = openssl_encrypt($data, 'AES-256-GCM', $key, OPENSSL_RAW_DATA, $iv, $tag);
$stored = base64_encode($iv . $tag . $encrypted);
✓ Fixed
// AES-256-GCM — authenticated encryption (confidentiality + integrity)
\$key  = random_bytes(32); // 256-bit key — store in secrets manager
\$iv   = random_bytes(12); // 96-bit IV — unique per encryption
\$tag  = '';

\$ciphertext = openssl_encrypt(\$plaintext, 'AES-256-GCM', \$key, OPENSSL_RAW_DATA, \$iv, \$tag);
\$stored     = base64_encode(\$iv . \$tag . \$ciphertext); // pack together

// Decrypt:
\$raw        = base64_decode(\$stored);
\$iv         = substr(\$raw, 0, 12);
\$tag        = substr(\$raw, 12, 16);
\$cipher     = substr(\$raw, 28);
\$decrypted  = openssl_decrypt(\$cipher, 'AES-256-GCM', \$key, OPENSSL_RAW_DATA, \$iv, \$tag);
if (\$decrypted === false) throw new \RuntimeException('Decryption failed — data may be tampered');

Added 15 Mar 2026
Edited 22 Mar 2026
Views 32
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
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 3 pings S 0 pings S 0 pings M 0 pings T 0 pings 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 3 pings S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Amazonbot 10 Perplexity 6 Unknown AI 2 Ahrefs 2 Google 1 SEMrush 1 Claude 1 Bing 1
crawler 24
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: Medium
⚡ Quick Fix
Use AES-256-GCM for all new encryption: openssl_encrypt($data, 'aes-256-gcm', $key, OPENSSL_RAW_DATA, $iv, $tag) — store $tag alongside $iv and $ciphertext and verify it before decrypting
📦 Applies To
PHP 7.1+ web cli
🔗 Prerequisites
🔍 Detection Hints
openssl_encrypt with CBC mode without HMAC; AES-ECB mode; reusing IV across encryptions; not storing/verifying GCM authentication tag
Auto-detectable: ✓ Yes semgrep psalm
⚠ Related Problems
🤖 AI Agent
Confidence: High False Positives: Medium ✗ Manual fix Fix: Medium Context: Function Tests: Update
CWE-326 CWE-327

✓ schema.org compliant