PHP password_hash 每个字符串的函数值不同

PHP password_hash function value isn't same for each string

我尝试使用 password_hash() PHP [=22 来散列用户密码=],它的功能是工作散列,不是常量。

<?php 
    echo password_hash('a',PASSWORD_BCRYPT,array(
            'cost' => 12
         ));
?>

第 4 次测试结果

1. y$SRmipqM7AsYkx3Xc8QGHNex69rGXeVyWGTYrh9T8sh1cP3UrdjfQi
2. y$zx.GUgtcake3wMfl3/YXXeG1.8mmHKyRruL3nWj8OmA.RbEYqeW6u
3. y$XQtmFplcehkgWLbGrOUsNOlXDU/NGrwZlt3HM88hLbUHXhjXNF4km
4. y$q9/OSZdDJw7af4Hw4MGlHeY7UMtWr9/Cj0nj/N6PaoilNoUBePt7O

如果你想使用password_hash()并获取常量哈希值(不确定复数...),在使用时添加一个salt。 (但不要,请参阅下面的警告

explained in the doc一样,如果不这样做,每次使用该函数时都会随机生成盐,因此生成的哈希值不会是常量。

<?php 
    echo password_hash('a',PASSWORD_BCRYPT,array(
            'salt' => $salt_defined_for_the_user,
            'cost' => 12,
         ));
?>

关于你应该使用的盐,这里有一个很好的解释 wmfrancia extracted from here:

SALTING

Passwords should always be salted before hashed. Salting adds a random string to the password so similar passwords don't appear the same in the DB. However if the salt is not unique to each user (ie: you use a hard coded salt) than you pretty much have made your salt worthless. Because once an attacker figures out one password salt he has the salt for all of them.

When you create a salt make sure it is unique to the password it is salting, then store both the completed hash and salt in your DB. What this will do is make it so that an attacker will have to individually crack each salt and hash before they can gain access. This means a lot more work and time for the attacker.


注意:你不应该尝试用你自己的盐来获取常量哈希值

我只是在这里回应你愿意拥有恒定的哈希值,但是正如 halfer and martinstoeckli 在评论中所说的那样,也在官方文档中指出,

Caution It is strongly recommended that you do not generate your own salt for this function. It will create a secure salt automatically for you if you do not specify one.

You really should not create your own salt, the function tries its best to create a safe and random one. When you store a user specific salt as your example shows, you do the same as password_hash() does anyway. It includes the salt in the hash-value so the function password_verify() can pick it up from there

Mike M. has a detailed description for .

正如一些建议使用 MD5,不要将其用于密码散列。

那么现在回答你的问题how to check a password matches

Password_Hash() 是生成一个密码哈希,它会生成一个随机盐,这个哈希将在哈希时使用。 你的最终结果将是:salt+hash,然而你可以在它的选项中使用这个方法给它一个salt但是让我们保持它自己完成它。

Password_Verify() 使用一个参数作为密码,一个参数作为散列密码。 正如我之前所说,散列密码是 salt+hash 这是有道理的 Password_Verify() 只需要这些而不是额外的 salt

所以 Password_Verify() 发生的事情是它取出盐并使用 Password_Hash() 和盐。 然后检查接收到的哈希值是否等于给定的哈希值。 如果匹配则为真,否则为假。

Password_Hash() Doc

Password_Verify() Doc


更新 18-04-2018 (d-m-Y)

WARNING

The salt option has been deprecated as of PHP 7.0.0.

It is now preferred to simply use the salt that is generated by default.

Why not to use MD5 for Password Hashing - PHP FaQ Answer

我认为您对无论尝试多少次都产生相同散列的旧方法感到困惑。

例如,MD5 () 会一直为相同的密码提供五个相同的哈希值..

Password_hash 始终为您提供不同的字符串,因为它每次 运行 包含不同的盐。

当您从数据库中检索哈希密码时(例如,根据用户提供的电子邮件) Password_verify 将一起读取 salt+pass 的整个字符串,将使用作为 salt 的第一个字符,并将此 salt 与用户提供的普通密码一起使用以对其进行加密。

然后它将结果与从数据库中提取的盐+散列的剩余部分进行比较(现在剩余的应该是散列..没有盐)。

我希望这能帮助您理解为什么总是得到不同的字符串和对相同的密码使用密码哈希。