天天看點

Bcrypt加密算法簡介

xl_echo編輯整理,歡迎轉載,轉載請聲明文章來源。更多IT、程式設計案例、資料請聯系QQ:1280023003

百戰不敗,依不自稱常勝,百敗不頹,依能奮力前行。——這才是真正的堪稱強大!!

本文轉載自:http://www.php.cn/php-weizijiaocheng-376004.html

前言

我們常常為了避免在伺服器受到攻擊,資料庫被拖庫時,使用者的明文密碼不被洩露,一般會對密碼進行單向不可逆加密——哈希。

常見的方式是:

哈希方式 加密密碼

md5(‘123456’) e10adc3949ba59abbe56e057f20f883e

md5(‘123456’ . ($salt = ‘salt’)) 207acd61a3c1bd506d7e9a4535359f8a

sha1(‘123456’) 40位密文

hash(‘sha256’, ‘123456’) 64位密文

hash(‘sha512’, ‘123456’) 128位密文

密文越長,在相同機器上,進行撞庫消耗的時間越長,相對越安全。

比較常見的哈希方式是 md5 + 鹽,避免使用者設定簡單密碼,被輕松破解。

password_hash

但是,現在要推薦的是 password_hash() 函數,可以輕松對密碼實作加鹽加密,而且幾乎不能破解。

$password = ‘123456’;

var_dump(password_hash( password,PASSWORDDEFAULT));vardump(passwordhash( p a s s w o r d , P A S S W O R D D E F A U L T ) ) ; v a r d u m p ( p a s s w o r d h a s h ( password, PASSWORD_DEFAULT));

password_hash 生成的哈希長度是 PASSWORD_BCRYPT —— 60位,PASSWORD_DEFAULT —— 60位 ~ 255位。PASSWORD_DEFAULT 取值跟 php 版本有關系,會等于其他值,但不影響使用。

每一次 password_hash 運作結果都不一樣,是以需要使用 password_verify 函數進行驗證。

$password = ‘123456’;

hash=passwordhash( h a s h = p a s s w o r d h a s h ( password, PASSWORD_DEFAULT);

var_dump(password_verify( password, p a s s w o r d , hash));

password_hash 會把計算 hash 的所有參數都存儲在 hash 結果中,可以使用 password_get_info 擷取相關資訊。

password=‘123456′; p a s s w o r d = ‘ 123456 ′ ; hash = password_hash( password,PASSWORDDEFAULT);vardump(passwordgetinfo( p a s s w o r d , P A S S W O R D D E F A U L T ) ; v a r d u m p ( p a s s w o r d g e t i n f o ( hash));

輸出

array(3) {

[“algo”]=>

int(1)

[“algoName”]=>

string(6) “bcrypt”

[“options”]=>

array(1) {

[“cost”]=>

int(10)

}

}

注意:不包含 salt

可以看出我目前版本的 PHP 使用 PASSWORD_DEFAULT 實際是使用 PASSWORD_BCRYPT。

password_hash( password, p a s s w o r d , algo, options)的第三個參數 o p t i o n s ) 的 第 三 個 參 數 options 支援設定至少 22 位的 salt。但仍然強烈推薦使用 PHP 預設生成的 salt,不要主動設定 salt。

當要更新加密算法和加密選項時,可以通過 password_needs_rehash 判斷是否需要重新加密,下面的代碼是一段官方示例

options=array(‘cost′=>11);//Verifystoredhashagainstplain−textpasswordif(passwordverify( o p t i o n s = a r r a y ( ‘ c o s t ′ => 11 ) ; / / V e r i f y s t o r e d h a s h a g a i n s t p l a i n − t e x t p a s s w o r d i f ( p a s s w o r d v e r i f y ( password, hash))//Checkifanewerhashingalgorithmisavailable//orthecosthaschangedif(passwordneedsrehash($hash,PASSWORDDEFAULT,$options))//Ifso,createanewhash,andreplacetheoldone$newHash=passwordhash($password,PASSWORDDEFAULT,$options);//Loguserinpasswordneedsrehash可以了解為比較 h a s h ) ) / / C h e c k i f a n e w e r h a s h i n g a l g o r i t h m i s a v a i l a b l e / / o r t h e c o s t h a s c h a n g e d i f ( p a s s w o r d n e e d s r e h a s h ( $ h a s h , P A S S W O R D D E F A U L T , $ o p t i o n s ) ) / / I f s o , c r e a t e a n e w h a s h , a n d r e p l a c e t h e o l d o n e $ n e w H a s h = p a s s w o r d h a s h ( $ p a s s w o r d , P A S S W O R D D E F A U L T , $ o p t i o n s ) ; / / L o g u s e r i n p a s s w o r d n e e d s r e h a s h 可 以 理 解 為 比 較 algo + option和passwordgetinfo( o p t i o n 和 p a s s w o r d g e t i n f o ( hash) 傳回值。

password_hash 運算慢

password_hash 是出了名的運作慢,也就意味着在相同時間内,密碼重試次數少,洩露風險降低。

password=‘123456′;vardump(microtime(true));vardump(passwordhash( p a s s w o r d = ‘ 123456 ′ ; v a r d u m p ( m i c r o t i m e ( t r u e ) ) ; v a r d u m p ( p a s s w o r d h a s h ( password, PASSWORD_DEFAULT));

var_dump(microtime(true));

echo “\n”;

var_dump(microtime(true));

var_dump(md5( password));for( p a s s w o r d ) ) ; f o r ( i = 0; i<999; i < 999 ; i++)

{

md5($password);

}

var_dump(microtime(true));

輸出

float(1495594920.7034)

string(60) “ 2y 2 y 10$9ZLvgzqmiZPEkYiIUchT6eUJqebekOAjFQO8/jW/Q6DMrmWNn0PDm”

float(1495594920.7818)

float(1495594920.7818)

string(32) “e10adc3949ba59abbe56e057f20f883e”

float(1495594920.7823)

password_hash 運作一次耗時 784 毫秒, md5 運作 1000 次耗時 5 毫秒。這是一個非常粗略的比較,跟運作機器有關,但也可以看出 password_hash 運作确實非常慢

繼續閱讀