Bcrypt in PHP: How to Hash Passwords Correctly and Quickly
\n\nIf you've ever wondered "How do you use bcrypt for hashing passwords in PHP?", you're not alone. This question on Stack Overflow has gathered thousands of views — and for good reason. Password hashing is the foundation of security for any web application, and bcrypt remains one of the most reliable and popular algorithms. In this article, we'll explore how to use bcrypt in PHP, how to configure it for maximum performance, and how to avoid common pitfalls.
\n\nWhy bcrypt? Because it is resistant to brute-force attacks thanks to built-in "salt" and adjustable complexity. But how do you ensure your website doesn't slow down with every login? That's what we'll discuss.
\n\nWhat is bcrypt and why is it better than MD5 or SHA1?
\n\nLet's set the record straight: never use MD5 or SHA1 for password hashing. These algorithms are designed for speed, not security. Bcrypt, on the other hand, is intentionally designed to be slow. It uses a cost factor, which determines how many hashing iterations are performed. The higher the cost factor, the longer the hash takes to compute — and the harder it is for an attacker to crack the password.
\n\nIn PHP, working with bcrypt is greatly simplified thanks to the password_hash() and password_verify() functions. They were introduced in PHP 5.5 and have since become the de facto standard.
How to use bcrypt in PHP: Basic example
\n\nLet's start simple. Here's how to register a user and save their password:
\n\n<?php\n// User registration\n$password = "MySuperP@ss123";\n$hash = password_hash($password, PASSWORD_BCRYPT);\n\n// Save $hash to the database (e.g., in the password_hash field)\necho $hash; // Will output something like $2y$10$...\n?>\n\nAnd here's how to verify the password during login:
\n\n<?php\n// User login\n$loginPassword = "MySuperP@ss123";\n$storedHash = "$2y$10$..."; // from the database\n\nif (password_verify($loginPassword, $storedHash)) {\n echo "Password is correct!";\n} else {\n echo "Invalid password.";\n}\n?>\n\nSimple, right? But the devil is in the details. Let's dive into the cost factor.
\n\nConfiguring the cost factor: Balancing security and speed
\n\nBy default, PASSWORD_BCRYPT uses a cost factor of 10. This means 2^10 = 1024 iterations. On a modern server, this takes approximately 0.1–0.2 seconds. That seems small, but if you have 1000 simultaneous logins, the time will start to add up.
How do you choose the optimal cost factor? There's a simple rule: it should be such that hashing a single password takes no more than 0.5 seconds on your server. You can test this using the password_hash() function with different values.
Here's an example performance test:
\n\n<?php\n$password = "test_password";\n$times = [];\n\nfor ($cost = 8; $cost <= 14; $cost++) {\n $start = microtime(true);\n password_hash($password, PASSWORD_BCRYPT, ['cost' => $cost]);\n $times[$cost] = microtime(true) - $start;\n}\n\nprint_r($times);\n?>\n\nOn a typical shared hosting environment, a cost factor of 10–12 will be optimal. If you have a powerful server, you can increase it to 13–14. But don't overdo it: a cost factor that is too high can cause your server to exhaust all its resources on hashing during an attack.
\n\nOptimizing bcrypt performance in PHP
\n\nNow let's move on to the most interesting part — how to make bcrypt faster without sacrificing security. Here are several proven strategies:
\n\n1. Caching results
\nIf a user enters the correct password, why hash it again on every request? You can cache the result for a short time (e.g., 5 minutes) using Redis or Memcached. This is especially