2014-02-16 51 views
1

作爲學習php的一部分,我想嘗試一個註冊和登錄頁面,但是,我正在關注如何使用MySQLI存儲密碼,但我沒有使用該密碼:在PHP中比較密碼的哈希值

散列密碼

$password1 = 'hello123'; 
// A higher "cost" is more secure but consumes more processing power 
$cost = 10; 

// Create a random salt 
$salt = strtr(base64_encode(mcrypt_create_iv(16, MCRYPT_DEV_URANDOM)), '+', '.'); 

// Prefix information about the hash so PHP knows how to verify it later. 
// "$2a$" Means we're using the Blowfish algorithm. The following two digits are the cost parameter. 
$salt = sprintf("$2a$%02d$", $cost) . $salt; 

// Value: 
// $2a$10$eImiTXuWVxfM37uY4JANjQ== 

// Hash the password with the salt 
$hash = crypt($password1, $salt); 

我卡上。但是取回密碼,這裏是該網站的代碼吧:

$username = 'Admin'; 
$password = 'gf45_gdf#4hg'; 

$sth = $dbh->prepare(' 
    SELECT 
    hash 
    FROM users 
    WHERE 
    username = :username 
    LIMIT 1 
    '); 

$sth->bindParam(':username', $username); 

$sth->execute(); 

$user = $sth->fetch(PDO::FETCH_OBJ); 

// Hashing the password with its hash as the salt returns the same hash 
if (crypt($password, $user->hash) === $user->hash) { 
    // Ok! 
} 

從我所看到的,他抓取數據庫中用戶的密碼的哈希值,並比較使用散列傳遞的密碼,並與數據庫中的密碼進行覈對。

我一直想這一點,但結果哈希是絕不相同的原始之一:

$pwdtocheck = 'hello123'; 

// no call do DB yet, doing this on the same page after hashing, the $hash is the same as above 
$pwdhash = crypt($pwdtocheck, $hash); 

// if I echo $pwdhash it's never exactly the same as the $hash. 
if ($pwdhash === $hash) { 
    echo "same pwd"; 
} 
+0

那[站點](http://alias.io/2010/01/store-passwords-safely-with-php-and-mysql/)不加載,所以我不能看到什麼內容與之相比。 –

+1

從PHP 5.5開始,您可以使用['password_hash()'](http://php.net/password_hash)。 –

+0

另請參閱Openwall的[PHP密碼哈希框架](http://www.openwall.com/phpass/)(PHPass)。它的可移植性和強化針對許多用戶密碼的常見攻擊。 – jww

回答

1

編輯:

我看現在你使用鹽時,你比較密碼。在您的線路:

$pwdhash = crypt($pwdtocheck, $hash); 

$hash變量在前面加上因爲crypt()會自動爲你做的鹽。 crypt()將從$hash中提取鹽,因爲它知道基於所用算法的鹽的預期長度。 See the documentation

對於上下文和尋找類似答案的人,我會保留原始答案。

編輯完

的密碼是不一樣的你,因爲你使用的是salt當您最初哈希把你的數據庫中的密碼,但你是不是醃製密碼後,當您覈對數據庫。

當您保存密碼時,您應該使用相同的鹽字符串,因爲您在登錄時檢查用戶密碼。通常,您將隨機爲每個密碼生成salt字符串(如您所做的那樣),然後將salt字符串與散列密碼(在同一列或其自己的列中)一起保存到數據庫,以便您可以使用相同的密碼鹽在登錄時檢查用戶的密碼。

請參閱https://crackstation.net/hashing-security.htm#salt以供參考。

+1

這就是我對鹽的感覺困惑的地方!我也考慮過存儲它,但我不確定我應該^^謝謝! – LanFeusT

+0

這不可能是問題,因爲'crypt()'函數包含生成的哈希值中的鹽值,爲了驗證,它會自動從存儲的哈希值中提取鹽值。 – martinstoeckli

+0

我會再看一遍,但是我在幾個地方閱讀過,當你想稍後比較密碼時,你必須存儲鹽。 – LanFeusT

0

我不能訪問你引用的文章,但我想象:

你需要檢查使用鹽作爲鹽而不是哈希。

crypt($pwdtocheck, $user->salt) == $user->hash

應該工作

2

我看不到您的代碼中的實際問題,也許您的數據庫字段小於60個字符,或者您正在比較不同的密碼。在任何情況下,都有一種更簡單更安全的哈希密碼方式,只需使用新功能password_hash()password_verify()即可。早期的PHP版本也存在compatibility pack

// Hash a new password for storing in the database. 
// The function automatically generates a cryptographically safe salt. 
$hashToStoreInDb = password_hash($password, PASSWORD_BCRYPT); 

// Check if the hash of the entered login password, matches the stored hash. 
// The salt and the cost factor will be extracted from $existingHashFromDb. 
$isPasswordCorrect = password_verify($password, $existingHashFromDb); 
+0

謝謝,我今晚會檢查一下! – LanFeusT