2013-02-27 184 views
1

我有一個簡單的密碼加密器,當用戶註冊時,它給了我一個哈希/鹽漬密碼來存儲在我的數據庫中。代碼:加密在登錄時比較哈希和鹽漬密碼

public static string GenerateHashWithSalt(string enteredPassword, string enteredSalt) 
    { 
     string sHashWithSalt = enteredPassword + enteredSalt; 
     byte[] saltedHashBytes = Encoding.UTF8.GetBytes(sHashWithSalt); 
     System.Security.Cryptography.HashAlgorithm algorithm = new System.Security.Cryptography.SHA256Managed(); 
     byte[] hash = algorithm.ComputeHash(saltedHashBytes); 
     return Convert.ToBase64String(hash); 
    } 

當用戶登錄時,我相信我不能簡單地把輸入的密碼改回通過這個代碼和比較,因爲它會給我不同的結果。我如何只需比較存儲的密碼和輸入的登錄密碼?

+1

也許我沒有記錯的話我的密碼的教訓,但它正是你應該做的,當你從用戶的密碼,您鹽和擁有它,然後比較醃製+哈希密碼在DB中。它應該是相同的字符串。沒有隨機性,它是一個完全確定性的函數。 – OopsUser 2013-02-27 19:54:21

+0

散列算法是冪等的:相同的輸入=相同的輸出。 – 2013-02-27 19:56:09

+3

請注意,單次迭代SHA-256不適合使用密碼哈希。我使用PBKDF2,使用'Rfc2898DeriveBytes'類至少10000次迭代。 – CodesInChaos 2013-02-27 20:02:34

回答

5

創建帳戶時,您將有一個password hash列,該列將由GenerateHashWithSalt(password, salt);填充,其中密碼由它們提供,然後salt將隨機生成。鹽隨後將與密碼哈希一起存儲。

然後,當您需要查看用戶名/密碼是否有效時,您可以使用storedpassword == GenerateHashWithSalt(providedPassword, saltFromDb)等。如果他們出來一樣的,那麼你知道他們輸入正確的密碼

+0

這完美謝謝。我在散列長度方面也遇到了一些麻煩,數據庫只有25個字符,並且散列很好,所以它們不匹配。不過,我也解決了這個問題。再次感謝 – ZeeeeeV 2013-02-27 19:59:02

+0

@ZeeeeeV我會繼續說非常小心編寫自己的認證。這是非常棘手的,有非常微妙的東西,似乎工作,但後來最終泄漏您的用戶帳戶信息。另外,如果你只是將哈希值修改爲25個字符來解決這個問題,那麼基本上你的哈希值會變弱。展開數據庫列或創建一個新的文章 – Earlz 2013-02-27 20:45:03

0

有幾個步驟來正確地做到這一點。

首先,你需要三樣東西:

  1. 由用戶提供的密碼。 (我們稱之爲p
  2. 您創建的隨機字符串。這被稱爲鹽(我們就叫它小號
  3. 加密散列函數(也稱之爲^h(X))

通過上述三件事情我們可以計算出^h '這就是我們想要存儲:^h'= ^h小號 + p

用戶的密碼永遠不會被存儲。我們只在我們的數據庫中存儲sh''。

鹽不需要加密。它只需要對數據庫中的每個密碼都是唯一的。

當用戶試圖在未來再次登錄,您將重新計算^h「使用存儲在數據庫中的原始的鹽。如果新的h'等於數據庫中的內容,那麼用戶的密碼是相同的。

2

我寫了一篇快速教程,教你如何處理哈希密碼等效方案。但是,根據您提出的問題,我應該告誡您,這只是確保安全登錄過程的第一步。如果你是初學者,你應該聘請安全專家或購買現成的解決方案,而不是試圖推出自己的產品。造成系統不安全的嚴重錯誤的方法的數量是巨大的

http://blogs.msdn.com/b/ericlippert/archive/tags/salt/

+1

感謝這篇文章,它肯定有助於傳播哈希密碼的知識。也許你可以用像BCrypt或PBKDF2這樣的密鑰派生函數來交換「現代」MD5,這會使得哈希更安全。 – martinstoeckli 2013-02-28 07:38:28