我正在使用Laravel的bcrypt
函数来散列密码。当我做,
bcrypt('secret')
我明白了
=> "$2y$10$mnPgYt2xm9pxb/c2I.SH.uuhgrOj4WajDQTJYssUbTjmPOcgQybcu"
但是,如果我再次运行它,我会得到
=> "$2y$10$J8h.Xmf6muivJ4bDweUlcu/BaNzI2wlBiAcop30PbPoKa0kDaf9xi"
等等...
那么,如果每次都得到不同的值,密码匹配过程是否会失败?
这就是bcrypt
应该如何运作的方式。见wikipedia。
Bcrypt在散列期间生成随机的128位盐。这个盐成为哈希的一部分,因此我们总是为相同的输入字符串获得不同的哈希值。随机盐实际上用于阻止暴力攻击。
由于哈希值不同,密码匹配过程不会失败。在tinker
中尝试以下操作
$hash1 = bcrypt('secret')
$hash2 = bcrypt('secret')
Hash::check('secret', $hash1)
Hash::check('secret', $hash2)
你应该在true
的情况下获得Hash::check
。
因此,即使哈希值不同,密码匹配也不会失败。
Bcrypt使用128位盐并加密192位魔术值。它利用了eksblowfish中昂贵的密钥设置。
bcrypt算法分两个阶段运行,如图3所示。在第一阶段,使用cost,salt和password调用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(字符串) - 在散列密码时手动提供盐。请注意,这将覆盖并防止自动生成salt。
如果省略,则每个密码哈希值都会通过password_hash()生成随机盐。这是预期的操作模式。
警告自PHP 7.0.0起,salt选项已被弃用。现在优选简单地使用默认生成的盐。
cost(整数) - 表示应该使用的算法成本。可以在crypt()页面上找到这些值的示例。
如果省略,将使用默认值10。这是一个很好的基准成本,但您可能需要考虑根据您的硬件增加它。
Bcrypt加密和解密如何工作: 内部bcrypt()使用PHP的内置password_hash()函数。 password_hash()每次都返回不同的值,因为它会在密码中附加一个随机字符串(“salt”)。 salt实际上包含在输出哈希中。
如果使用相同的盐对相同的密码进行哈希处理,则始终会获得相同的输出。因此,password_verify()查看存储的哈希,提取salt,然后使用相同的盐哈希给定的密码。