Table of Contents
4. Password Handling — Modern, Safe, and Simple
Passwords are more than strings.
They are secrets — and secrets require careful handling.
Modern PHP gives us safe, simple tools for password hashing and verification.
The danger comes not from complexity, but from invention.
Most password vulnerabilities arise when developers try to be clever.
This page introduces the mental model for handling passwords in a way that is modern, predictable, and secure by default.
1. Never Store Passwords — Store Hashes
A password should never appear:
- in plaintext
- in logs
- in emails
- in database dumps
- in debugging output
- in session data
The only safe representation is a one‑way hash.
- A hash is not encryption.
- It cannot be reversed.
- It is a fingerprint of the password, not the password itself.
2. Use password_hash() — It Chooses Safe Defaults
Modern PHP gives us a simple, safe API:
$hash = password_hash($password, PASSWORD_DEFAULT);
This:
- uses a strong algorithm (currently bcrypt or Argon2)
- generates a random salt
- embeds the algorithm and cost in the hash
- produces a self‑contained, future‑proof string
We do not need to:
- generate your own salt
- choose your own algorithm
- tune parameters manually
- store metadata separately
PHP handles all of it.
3. Use password_verify() — It Knows How to Check
To verify a password:
if (password_verify($password, $hash)) { // authenticated }
This:
- extracts the algorithm from the hash
- extracts the salt
- applies the correct cost
- compares safely
You do not need to know how the hash was created.
The hash itself contains the instructions.
4. Use password_needs_rehash() — For Future Upgrades
Algorithms evolve.
Costs change.
Hardware gets faster.
PHP lets us upgrade hashes automatically:
if (password_needs_rehash($hash, PASSWORD_DEFAULT)) { $hash = password_hash($password, PASSWORD_DEFAULT); // store the new hash }
This keeps our system modern without migrations or downtime.
5. Never Roll Your Own Crypto
Do not:
- write your own hashing function
- use MD5, SHA1, or SHA256 for passwords
- concatenate salts manually
- invent token formats
- use encryption instead of hashing
Security collapses when developers invent mechanisms.
Use:
- password_hash()
- password_verify()
- password_needs_rehash()
These are safe, simple, and maintained.
6. Use Argon2 When Available
If your PHP installation supports Argon2:
$hash = password_hash($password, PASSWORD_ARGON2ID);
Argon2ID is:
- memory‑hard
- GPU‑resistant
- modern
- recommended for new systems
But PASSWORD_DEFAULT is still safe.
It will automatically switch to better algorithms over time.
7. Do Not Impose Arbitrary Password Rules
Security is not improved by:
- requiring special characters
- forcing uppercase letters
- banning repeated characters
- limiting length unnecessarily
These rules frustrate users and encourage weak patterns.
Better defaults:
- allow long passwords
- allow passphrases
- avoid arbitrary complexity rules
- enforce a reasonable minimum length (e.g., 8–12 characters)
Length is strength.
8. Rate‑Limit Authentication Attempts
Password hashing is safe
— but brute force is still a risk.
Use:
- rate limiting
- exponential backoff
- IP throttling
- account lockouts (temporary, not permanent)
Security is not just about the hash
— it’s about the boundary around it.
9. Never Log Passwords or Hashes
Logging passwords is catastrophic.
Logging hashes is unnecessary and risky.
Avoid:
- dumping request bodies
- logging form submissions
- logging authentication failures with raw input
Logs live forever. Treat them as hostile territory.
Summary
Modern password handling in PHP is simple because the language gives you safe defaults.
A secure system:
- never stores passwords
- uses password_hash()
- verifies with password_verify()
- upgrades with password_needs_rehash()
- avoids custom crypto
- supports long passphrases
- rate‑limits authentication
- keeps secrets out of logs
Security is not about cleverness.
It’s about choosing the safe path and staying on it.
This page describes secure defaults and common practices in modern PHP. It is not a complete security guide, and it does not replace formal audits or framework‑specific documentation. These principles are consistent enough to be useful, but security always requires context, judgment, and ongoing review.
