4

我正在尝试使用password_hash() PHP 函数来散列用户密码。但是,它的函数是工作散列,而不是恒定的。

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

第四次测试结果

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

3 回答 3

9

正如一些人建议使用 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() 文档

Password_Verify() 文档


更新 18-04-2018 (dmY)

警告

PHP 7.0.0起, salt 选项已被弃用

现在首选简单地使用默认生成的盐。

有关盐渍的更多信息 - Veve 的 SO 回答如下

为什么不使用 MD5 进行密码散列 - PHP 常见问题解答

为什么不使用 MD5 进行密码散列 - SO 答案:Silverlightfox

于 2015-02-20T10:36:18.460 回答
2

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

文档中所述,如果不这样做,则每次使用该函数时都会随机生成盐,因此生成的哈希不会是恒定的。

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

关于你应该使用的盐,这里是从这里提取的wmfrancia的一个很好的解释:

密码应始终在散列之前加盐。Salting 会在密码中添加一个随机字符串,因此类似的密码在数据库中不会出现相同的情况。但是,如果盐不是每个用户唯一的(即:您使用硬编码的盐),那么您几乎会使您的盐一文不值。因为一旦攻击者找出一个密码盐,他就拥有了所有这些盐。

当您创建盐时,请确保它对于盐的密码是唯一的,然后将完成的哈希和盐都存储在您的数据库中。这样做的目的是使攻击者必须单独破解每个盐和哈希,然后才能获得访问权限。这意味着攻击者需要更多的工作和时间。


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

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

注意强烈建议您不要为此函数生成自己的盐。如果您不指定,它将自动为您创建一个安全的盐。

.

您真的不应该创建自己的盐,该功能会尽力创建一个安全且随机的盐。当您存储用户特定的盐时,如您的示例所示,您的操作与 password_hash() 一样。它在哈希值中包含盐,因此函数 password_verify() 可以从那里获取它

Mike M.在他的回答中对使用的password_verify()替代有详细的描述。

于 2015-02-20T10:23:01.747 回答
0

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

例如,MD5 () 将始终为您提供相同密码的相同哈希值。

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

当您从数据库中检索哈希密码时(例如,基于用户提供的电子邮件) Password_verify 将一起读取 salt+pass 的整个字符串,将使用作为 salt 的第一个字符并将此 salt 与纯文本一起使用用户提供的密码来加密它。

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

我希望这有助于你理解为什么你总是得到不同的字符串,你对相同的密码使用密码哈希。

于 2015-08-24T05:06:58.253 回答