PHP 加密用户密码 How to store passwords safely with PHP and MySQL

  1. Do not store password as plain text
  2. Do not try to invent your own password security
  3. Do not ‘encrypt’ passwords
  4. Do not use MD5
  5. Do not use a single site-wide salt
  6. What you should do
  • Use a cryptographically strong hashing function like bcrypt (see PHP’s crypt() function).
  • Use a random salt for each password.
  • Use a slow hashing algorithm to make brute force attacks practically impossible.
  • For bonus points, regenerate the hash every time a users logs in.
$username = 'Admin';
$password = 'gf45_gdf#4hg';

// A higher "cost" is more secure but consumes more processing power
$cost = 10;

// Create a random salt
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.');

// Prefix information about the hash so PHP knows how to verify it later.
// "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter.
$salt = sprintf("$2a$%02d$", $cost) . $salt;

// Value:
// $2a$10$eImiTXuWVxfM37uY4JANjQ==

// Hash the password with the salt
$hash = crypt($password, $salt);

// Value:
// $2a$10$eImiTXuWVxfM37uY4JANjOL.oTxqp7WylW7FCzx2Lc7VLmdJIddZq

In the above example we turned a reasonably strong password into a hash that we can safely store in a database. The next time the user logs in we can validate the password as follows:

$username = 'Admin';
$password = 'gf45_gdf#4hg';

// For brevity, code to establish a database connection has been left out

$sth = $dbh->prepare('
  FROM users
    username = :username

$sth->bindParam(':username', $username);


$user = $sth->fetch(PDO::FETCH_OBJ);

// Hashing the password with its hash as the salt returns the same hash
if ( hash_equals($user->hash, crypt($password, $user->hash)) ) {
  // Ok!

A few additional tips to prevent user accounts from being hacked:

  • Limit the number of failed login attempts.
  • Require strong passwords.
  • Do not limit passwords to a certain length (remember, you’re only storing a hash so length doesn’t matter).
  • Allow special characters in passwords, there is no reason not to.

注意:hash_equals (PHP 5 >= 5.6.0) 如果你的php版本 phpversion()不够,可以尝试使用下面的代码



 This library requires PHP >= 5.3.7 OR a version that has the $2y fix backported into it (such as RedHat provides). Note that Debian’s 5.3.3 version is NOT supported.


require "lib/password.php";
echo "Test for functionality of compat library: " . (PasswordCompatbinarycheck() ? "Pass" : "Fail");
echo "n";


Creating Password Hashes

To create a password hash from a password, simply use the password_hash function.

$hash = password_hash($password, PASSWORD_BCRYPT);

Note that the algorithm that we chose is PASSWORD_BCRYPT. That’s the current strongest algorithm supported. This is the BCRYPT crypt algorithm. It produces a 60 character hash as the result.

BCRYPT also allows for you to define a cost parameter in the options array. This allows for you to change the CPU cost of the algorithm:

$hash = password_hash($password, PASSWORD_BCRYPT, array("cost" => 10));

That’s the same as the default. The cost can range from 4 to 31. I would suggest that you use the highest cost that you can, while keeping response time reasonable (I target between 0.1 and 0.5 seconds for a hash, depending on use-case).

Another algorithm name is supported:


This will use the strongest algorithm available to PHP at the current time. Presently, this is the same as specifying PASSWORD_BCRYPT. But in future versions of PHP, it may be updated to use a stronger algorithm if one is introduced. It can also be changed if a problem is identified with the BCRYPT algorithm. Note that if you use this option, you are strongly encouraged to store it in a VARCHAR(255) column to avoid truncation issues if a future algorithm increases the length of the generated hash.

It is very important that you should check the return value of password_hash prior to storing it, because a false may be returned if it encountered an error.

Verifying Password Hashes

To verify a hash created by password_hash, simply call:

    if (password_verify($password, $hash)) {
        /* Valid */
    } else {
        /* Invalid */

That’s all there is to it.

Rehashing Passwords

From time to time you may update your hashing parameters (algorithm, cost, etc). So a function to determine if rehashing is necessary is available:

    if (password_verify($password, $hash)) {
        if (password_needs_rehash($hash, $algorithm, $options)) {
            $hash = password_hash($password, $algorithm, $options);
            /* Store new hash in db */





本文:PHP 加密用户密码 How to store passwords safely with PHP and MySQL

Leave a Reply