How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: Securely Hash Passwords in PHP (password_hash, Argon2id)
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Web Development > Securely Hash Passwords in PHP (password_hash, Argon2id)
Web Development

Securely Hash Passwords in PHP (password_hash, Argon2id)

how7o
By how7o
Last updated: May 23, 2026
6 Min Read
Securely hash passwords in PHP with password_hash
SHARE

To create a secure password hash in PHP, use the built-in password_hash function with PASSWORD_DEFAULT (bcrypt) or PASSWORD_ARGON2ID for the current cryptographic best practice. Never use MD5 or SHA — those are fast hashes built for files, not passwords. Verify on login with password_verify and re-hash old hashes when a stronger algorithm becomes available.

Contents
  • Hash and verify
  • Argon2id — the modern recommendation
  • Re-hash old hashes on login
  • Why MD5 / SHA-256 are wrong for passwords
  • Database column size
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-05-17 on PHP 8.3. Originally published 2023-01-03, rewritten and updated 2026-05-17.

Hash and verify

// Registration / password change
$hash = password_hash($plaintext, PASSWORD_DEFAULT);
// Store $hash in the database (255 chars is a safe column size)

// Login
if (password_verify($plaintext, $hash)) {
    // Authentic — log the user in
} else {
    // Wrong password
}

PASSWORD_DEFAULT currently means bcrypt. PHP’s commitment is that this constant always points at the strongest algorithm shipped with that PHP version — using it future-proofs your code.

PHP password hashing — password_hash + verify, PASSWORD_DEFAULT bcrypt, Argon2id, password_needs_rehash

Argon2id — the modern recommendation

// PHP 7.3+
$hash = password_hash($plaintext, PASSWORD_ARGON2ID);

// Tunable options
$hash = password_hash($plaintext, PASSWORD_ARGON2ID, [
    'memory_cost' => 65536,   // 64 MB — RAM use
    'time_cost'   => 4,       // iterations
    'threads'     => 2,
]);

Argon2id won the 2015 Password Hashing Competition and is the current cryptographic best practice. It’s more resistant to GPU-accelerated brute force than bcrypt because it’s memory-hard — every guess requires significant RAM. The cost parameters above are sensible defaults; raise them if your hardware can handle slower hashes (server-side login is the only place this runs).

Re-hash old hashes on login

if (password_verify($plaintext, $user->password_hash)) {
    // Authenticate first

    if (password_needs_rehash($user->password_hash, PASSWORD_DEFAULT)) {
        $user->password_hash = password_hash($plaintext, PASSWORD_DEFAULT);
        $user->save();
    }

    // ... log in
}

When PHP upgrades the default algorithm (or you raise the cost), password_needs_rehash returns true for hashes that don’t match the current settings. Re-hashing during login (when you have the plaintext) upgrades active users transparently over time. Dormant users are still on the old algorithm, which is acceptable — they’re not the attack surface.

Why MD5 / SHA-256 are wrong for passwords

// DON'T DO THIS
$hash = md5($plaintext);                       // ~10 billion guesses/sec on a GPU
$hash = hash('sha256', $plaintext);            // billions/sec, same problem
$hash = sha1($plaintext . $salt);              // billions/sec, salted but still fast

MD5/SHA were designed for fast hashing of arbitrary data (signatures, integrity checks). That speed is a security bug when applied to passwords — an attacker with a stolen password table can try every word in every dictionary in hours. password_hash with bcrypt or Argon2id is intentionally slow (~100 ms per guess on standard hardware), turning a hours-long attack into one that takes years.

Database column size

$table->string('password', 255);   // safe ceiling for any algorithm

bcrypt produces a 60-character hash; Argon2id strings can be 96+. Use VARCHAR(255) to leave headroom for future algorithm upgrades without schema changes.

Frequently asked questions

Why is MD5/SHA-256 wrong for passwords?

Those are fast cryptographic hashes — designed for hashing files and signatures, where speed is a feature. For passwords, fast is the opposite of what you want: an attacker who steals the password file can brute-force billions of MD5 hashes per second on a GPU. password_hash uses bcrypt (or Argon2id), which is intentionally slow — billions of guesses per second drop to thousands.

How do I upgrade existing user passwords to a stronger hash?

Re-hash on next login. After verifying with password_verify, call password_needs_rehash($hash, PASSWORD_DEFAULT) — returns true if the stored hash uses an older algorithm than your current default. If yes, hash the plaintext (which you have during login) with the current default and update the row. Over time, every active user’s password gets upgraded transparently.

Should I salt manually?

No — password_hash generates a cryptographically random salt and embeds it in the result. The full hash string includes algorithm version, cost, salt, and the actual digest. You store one column and the salt comes along automatically. Manually salting (concatenating before hashing) used to be standard advice; the password_* API made it obsolete.

What’s the difference between bcrypt and Argon2?

Both are intentionally slow password-hashing functions. Bcrypt is older (1999), battle-tested, the current PHP default. Argon2id (PASSWORD_ARGON2ID, available since PHP 7.3) won the Password Hashing Competition in 2015 and is the current cryptographic recommendation — it’s more resistant to GPU/ASIC attacks via memory hardness. For new projects, Argon2id is the better pick; for compatibility with existing bcrypt hashes, stick with the default.

Related guides

  • How to Create a Login and Registration System in Laravel
  • How to Fix Missing Authorization Header in PHP Requests
  • How to Validate an Email Address in PHP

References

PHP password_hash: php.net/manual/en/function.password-hash.php. PHP password_verify: php.net/manual/en/function.password-verify.php. PHP password_needs_rehash: php.net/manual/en/function.password-needs-rehash.php. OWASP password storage cheat sheet: cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html.

TAGGED:AuthenticationphpSecurity

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article yum/dnf -y flag explained What Does the -y Flag Do in yum / dnf / apt-get?
Next Article Laravel old() helper for repopulating form inputs How Laravel’s old() Helper Works (and Why It Sometimes Doesn’t)
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Run Laravel queue workers with Supervisor
How to Run Laravel Queue Workers in Production with Supervisor
May 23, 2026
Nginx as a reverse proxy for a Node.js app on Ubuntu
How to Set Up Nginx as a Reverse Proxy for Node.js on Ubuntu
May 23, 2026
Install and configure Redis on Ubuntu for Laravel and WordPress
How to Install and Configure Redis on Ubuntu (for Laravel & WordPress)
May 23, 2026
Harden a fresh Ubuntu VPS with UFW, Fail2Ban, and SSH key auth
How to Harden a Fresh Ubuntu VPS: UFW + Fail2Ban + SSH Key Auth
May 23, 2026
Set up Let's Encrypt SSL with Certbot on Ubuntu
How to Set Up Let’s Encrypt SSL with Certbot on Ubuntu (Apache & Nginx)
May 23, 2026

You Might Also Like

DataTables default sort order — order: [[1, 'desc']] config
Web Development

How to Change the Default Sort Order in DataTables

4 Min Read
Laravel get config variable — config() helper and Config facade resolving dotted keys
Web Development

How to Get Config Variables in Laravel

7 Min Read
Debug PHP like console.log using error_log and server logs
Web Development

How to Debug in PHP Like console.log (echo, error_log, WordPress debug.log)

6 Min Read
Use a JavaScript variable as an object key
Web Development

How to Use a Variable as an Object Key in JavaScript

5 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?