Laravel 5.2 默认的密码加密,怎么加点盐?

kanjiushi006
  • 1.6k

laravel 5.2 默认的密码加密,怎么加点盐?
顺便弱弱的问一下:盐是啥?

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }
回复
阅读 8.5k
3 个回答
jokester
  • 6.7k

bcrypt生成的密码hash中已经包含盐了


盐是用于防止从彩虹表中反查出密码的随机字符串

没有盐的情况: 用户密码是123456, 傻程序员就直接在数据库保存hash('123456'), 坏人拿到数据库后就可以直接从这个hash反查出密码

有盐的情况: 用户仍然用123456, 正常程序员在数据库保存hash('123456'+盐)和盐. 坏人拿到数据库后很难从这个hash还原出密码 (暴力破解仍然可能, 但是至少把低成本的彩虹表废掉了)

gclove
  • 1.4k

https://github.com/laravel/framework/blob/5.1/src/Illuminate/Hashing/BcryptHasher.php

查看这部分的源代码可得,

    // Laravel 的 bcrypt 就是 
$hash = password_hash($value, PASSWORD_BCRYPT, ['cost' => 10]);

因为 password_hash 使用的是 crypt 算法, 因此参与计算 hash值的:

算法(就像身份证开头能知道省份一样, 由盐值的格式决定), cost(默认10) 和 盐值 是在$hash中可以直接看出来的!

所以说, Laravel 中bcrypt的盐值是PHP自动随机生成的字符, 虽然同一个密码每次计算的hash不一样.

但是通过 $hash 和 密码, 却可以验证密码的正确性!


具体来说, 比如这个

$hash = password_hash('password',PASSWORD_BCRYPT,['cost' => 10]);
echo $hash;
// 比如我这次算的是
// $hash = '$2y$10$DyAJOutGjURG9xyKgAaCtOm4K1yezvgNkxHf6PhuLYBCENk61bePm';

那么我们从这个 crypt的hash值中可以看到,
因为以$2y$开头, 所以它的算法是 CRYPT_BLOWFISH .

同时 CRYPT_BLOWFISH 算法盐值格式规定是 :

以$2y$开头 + 一个两位cost参数 + $ + 22位随机字符("./0-9A-Za-z")

$hash(CRYPT_BLOWFISH是固定60位) = 盐值 + 31位单向加密后的值

参见: https://secure.php.net/manual/en/function.crypt.php


验证密码

if (password_verify('password', $hash)) {
    echo '密码正确.';
} else {
    echo '密码错误!';
}

// 原理是: 

if ($hash === crypt('password', '$2y$10$DyAJOutGjURG9xyKgAaCtO')) {
    echo '密码正确.';
} else {
    echo '密码错误!';
}

如果自己写用户系统并且使用PHP5.5+或PHP7,可以考虑使用PHP自带的password_hash()和password_verify(),非常方便

宣传栏