2012-10-03 37 views
0

我有一個登錄系統不區分大小寫的用戶名和密碼鹽

其中,例如,Joe可以用用戶名登錄joe沒有任何問題。

目前,我正在使用使用用戶名作爲鹽的密碼加密。這就造成登錄問題。例如,

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`) 
$stmt->bindValue(':username', $_POST['user']); 

這工作正常。故障涉及的密碼:

SELECT * FROM `users` WHERE LOWER(`username`) = LOWER(`:username`) 
    AND `password` = :password 
$stmt->bindValue(':username', $_POST['user']); 
$stmt->bindValue(':password', encrypt($_POST['password'], $_POST['user'])); //encrypt(password, salt) 

正如你所看到的,密碼加密不會與數據庫檢查,因爲用戶已經用joe代替Joe

有一種解決方法,以這種登錄,或者我應該使用別的東西作爲鹽?如果是這樣,我應該如何使用鹽?這是我的加密功能:

function encrypt($password, $salt) { 
    return base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5($salt), $password, MCRYPT_MODE_CBC, md5(md5($salt)))); 
} 
+3

將用戶名用作鹽不是一個好主意。鹽應該是中等長度,隨機和非ASCII。每次用戶更改密碼時也應更改。 – SLaks

+0

@SLaks哦,那麼你需要儲存鹽嗎? – Norse

+0

@ Norse:的確如此。 – SLaks

回答

2

首先,使用strtolower($_POST['user'])作爲鹽有什麼問題?它看起來會起作用。

現在一般來說,鹽應該是不可預測的。用戶名並不是真的那麼難以預測,因此雖然這不會是世界末日,但如果用隨機生成的適中長度的字符串替換用戶名,用戶的安全性會更好(它不必是加密強度隨機,只是不可預知的)。

但是這裏最大的問題是使用MD5,這在一段時間內被認爲是不安全的。如果切換到其他散列函數,安全性會提高; SHA-1並不是一個特別糟糕的選擇(它確實有一個不理想的特性:計算起來很快),但最適合這種應用的是具有可變加載因子的哈希函數,如bcrypt

1

您遇到的問題是用戶名不能用作鹽的一個原因。散列密碼的更好方法是使用crypt()。你只需要生成一個隨機鹽來使用它。它返回的字符串包含散列和散列算法,因此如果您想要更改算法或難度,而無需重寫代碼。只要你的散列是7位安全的,整個字符串將是,所以你不需要base64_encode()任何東西。

2

這裏有幾個問題:

  1. 的鹽的情況下,靈敏度
  2. 你的密碼「加密」的方法

第一個問題是你問什麼所以讓我們來看看這個。

因此,您的密碼被用戶名稱醃製,您希望能夠使用用戶在登錄期間輸入的用戶名作爲鹽。如果你決定採用鹽的標準化計劃,這將起作用。而不是像輸入一樣使用它,在將它用於你的函數之前,將它轉換爲小寫或大寫。

另一種方法是對數據庫執行兩個查詢:一個用於在存儲用戶名時提取用戶名,另一個用於實際檢查密碼。這不是最佳的,但它確實是你的麻煩中最少的。

有沒有解決方法,或者我應該使用別的東西作爲鹽?如果是這樣,我應該如何使用鹽?

既然你問了,讓我們看看第二個問題:你的密碼方法「加密」。

試圖發明自己的密碼散列/加密方案從來不是一個好主意,原因有很多。您最好的選擇是使用已被廣泛接受的密碼散列方案,例如bcrypt或PBKDF2的一些衍生物。這些都很棒,因爲它們都包括鹽和關鍵拉伸。它們被設計得很慢(相對來說,反正),所以強制這些類型的哈希值在計算上非常昂貴。

使用上述密碼散列方案之一也將解決您的第一個問題,因爲這些方案使用內置的每個用戶鹽。根據你選擇實施這些方案的方式,你不會(不應該)需要提供你自己的鹽。頂級圖書館將爲您生成鹽。

嘗試採取看看這些庫的密碼哈希:

相關問題