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

Laravel 5: using bcrypt on same string gives different values

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

bcrypt('secret')

我明白了

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

但是如果我再次运行它,我得到

=> "y$J8h.Xmf6muivJ4bDweUlcu/BaNzI2wlBiAcop30PbPoKa0kDaf9xi"

等等...

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

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

Bcrypt 在散列过程中生成一个 随机 128 位盐 。这个 salt 成为散列的一部分,因此对于相同的输入字符串我们总是得到不同的散列值。随机盐实际上用于阻止暴力攻击

密码匹配过程不会因为哈希值不同而失败。 在 tinker

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

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

Hash::check 两种情况下,您都应该得到 true

所以即使哈希值不同,密码匹配也不会失败

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

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

在 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 支持的选项:

salt (string) - 手动提供在对密码进行哈希处理时使用的盐。请注意,这将覆盖并防止自动生成盐。

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

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.

cost (integer) - 表示应该使用的算法成本。这些值的示例可以在 crypt() 页面上找到。

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

Bcrypt 加密和解密的工作原理:
bcrypt() 在内部使用 PHP 的内置 password_hash() 函数。 password_hash() returns 每次都有不同的值,因为它将随机字符串 ("salt") 附加到密码。盐实际上包含在输出哈希中。

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