Laravel 5:在相同的字符串上使用bcrypt会给出不同的值

时间:2016-08-29 03:10:36

标签: laravel laravel-5 bcrypt

我使用Laravel的bcrypt函数来散列密码。当我这样做时,

bcrypt('secret')

我得到了

=> "$2y$10$mnPgYt2xm9pxb/c2I.SH.uuhgrOj4WajDQTJYssUbTjmPOcgQybcu"

但是,如果我再次运行它,我会

=> "$2y$10$J8h.Xmf6muivJ4bDweUlcu/BaNzI2wlBiAcop30PbPoKa0kDaf9xi"

依旧......

那么,如果每次都得到不同的值,密码匹配过程是否会失败?

2 个答案:

答案 0 :(得分:20)

这就是bcrypt的工作方式。请参阅wikipedia

Bcrypt在散列期间生成随机128位salt 。此 salt 成为哈希的一部分,因此我们总是为同一输入字符串获取不同的哈希值。随机盐实际上用于阻止暴力攻击

由于哈希值不同,密码匹配过程不会失败。 请在tinker

中尝试以下操作
$hash1 = bcrypt('secret')
$hash2 = bcrypt('secret')

Hash::check('secret', $hash1)
Hash::check('secret', $hash2)

true

的两种情况都应该Hash::check。{/ 1}

因此,即使哈希值不同,密码匹配也不会失败。

答案 1 :(得分:0)

Bcrypt 使用128位的salt并加密192位的magic值。它利用了eksblowfish中昂贵的密钥设置。

bcrypt算法分两个阶段运行,如图3所示。在第一个阶段,使用成本,盐和密码调用EksBlowfishSetup来初始化eksblowfish的状态。 bcrypt的大部分时间都花在了昂贵的密钥调度中。然后,使用eksblowfish在ECB模式下以前一阶段的状态加密192位值``OrpheanBeholderScryDoubt''64次。输出是成本和128位盐与加密循环的结果连接在一起。

enter image description here

它在laravel中如何工作:

if (! function_exists('bcrypt')) {
    /**
     * Hash the given value against the bcrypt algorithm.
     *
     * @param  string  $value
     * @param  array  $options
     * @return string
     */
    function bcrypt($value, $options = [])
    {
        return app('hash')->driver('bcrypt')->make($value, $options);
    }
}

PASSWORD_BCRYPT支持的选项:

盐(字符串)-在散列密码时手动提供盐。请注意,这将覆盖并阻止盐自动生成。

如果省略,password_hash()将为散列的每个密码生成随机盐。这是预期的操作模式。

  

警告从PHP 7.0.0起不建议使用salt选项。就是现在   首选仅使用默认情况下生成的盐。

费用(整数)-表示应使用的算法费用。这些值的示例可以在crypt()页面上找到。

如果省略,将使用默认值10。这是一个不错的基准成本,但是您可能要考虑根据硬件而增加它。

Bcrypt加密和解密的工作方式:
内部使用bcrypt()会使用PHP的内置password_hash()函数。 password_hash()每次都会返回不同的值,因为它会在密码后附加一个随机字符串(“ salt”)。盐实际上包含在输出哈希中。

如果使用相同的盐对相同的密码进行哈希处理,则将始终获得相同的输出。因此password_verify()会查看存储的哈希,提取盐,然后使用相同的盐对给定的密码进行哈希处理。