laravel 5.2 預設的密碼加密,怎麼加點鹽?
順便弱弱的問一下:鹽是啥?
protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']), ]); }
回複內容:
laravel 5.2 預設的密碼加密,怎麼加點鹽?
順便弱弱的問一下:鹽是啥?
protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => bcrypt($data['password']), ]); }
bcrypt產生的密碼hash中已經包含鹽了
鹽是用於防止從彩虹表中反查出密碼的隨機字串
沒有鹽的情況: 使用者密碼是123456, 傻程式員就直接在資料庫儲存hash('123456'), 壞人拿到資料庫後就可以直接從這個hash反查出密碼
有鹽的情況: 使用者仍然用123456, 正常程式員在資料庫儲存hash('123456'+鹽)和鹽. 壞人拿到資料庫後很難從這個hash還原出密碼 (暴力破解仍然可能, 但是至少把低成本的彩虹表廢掉了)
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(),非常方便