User Tools

Site Tools


security_fundamentals:php_password_handling

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.


security_fundamentals/php_password_handling.txt · Last modified: by editor