Asp.net

有效的密碼加密

  • November 13, 2015

我查看了 StackOverflow 問題“密碼加密/數據庫層 AES 或應用程序層 AES”,我想在註冊時有效且高效地散列我的密碼(網路應用程序),然後能夠檢查它們是登錄時正確。我正在使用 VB,但使用 C# 很舒服。

我很想使用“.NET Encryption Simplified”中描述的 Jeff Atwood 的加密類,因為它真的很容易理解。它有一個散列類——但我不知道如何“登錄”並在散列後比較散列。這是 Jeff 使用他的 Encryption 類展示他的雜湊方法:

Sub DemoHash()
   Dim d As New Encryption.Data( _
       "{ts '2004-10-09 08:10:04'}The world is beautiful and needs caring by its children")

   Dim hash As New Encryption.Hash(Encryption.Hash.Provider.SHA1)
   Dim hash2 As New Encryption.Hash(Encryption.Hash.Provider.SHA256)
   Dim hash3 As New Encryption.Hash(Encryption.Hash.Provider.SHA384)
   Dim hash4 As New Encryption.Hash(Encryption.Hash.Provider.SHA512)
   Dim hash5 As New Encryption.Hash(Encryption.Hash.Provider.MD5)
   Dim hash6 As New Encryption.Hash(Encryption.Hash.Provider.CRC32)

   hash.Calculate(d)
   hash2.Calculate(d)
   hash3.Calculate(d)
   hash4.Calculate(d)
   hash5.Calculate(d)

   Console.WriteLine("SHA1:   " & hash.Value.Hex)
   Console.WriteLine("SHA256: " & hash2.Value.Hex)
   Console.WriteLine("SHA384: " & hash3.Value.Hex)
   Console.WriteLine("SHA512: " & hash4.Value.Hex)
   Console.WriteLine("MD5:    " & hash5.Value.Hex)
   Console.WriteLine("CRC32:  " & hash6.Calculate(d).Hex)
   Console.WriteLine()

   Dim salt As New Encryption.Data("salty!")
   Console.WriteLine("Salted CRC32:  " & hash6.Calculate(d, salt).Hex)

   Console.WriteLine("Press ENTER to continue...")
   Console.ReadLine()
End Sub

所以我的問題是:

  1. 我可以加密密碼(儘管我無意儲存它)並散列一個字元串。如果我有一個名為“barry”的使用者,其密碼為“fishlegs”,那麼儲存和檢索他的密碼的最佳方法是什麼?
  2. 在 SQL Server 中;binary 或 nvarchar 是儲存雜湊的最佳選擇嗎?
  3. 基於“巴里”和他的密碼,雜湊儲存的有效方法是什麼?它是附加到鹽的“魚腿”的加密嗎?

密碼學很難!

感謝任何可以提供幫助的人…

嗯,我認為您只是缺少一些與散列如何工作相關的基本概念。讓我試著簡要解釋一下。我將從簡單開始,然後詳細說明我的答案,所以請通讀全文,開頭的資訊不安全。

您想用來儲存密碼的是一種稱為“單向雜湊”的函式。這意味著,對於您提供給函式的任何輸入,相同的輸入將始終給出相同的結果。但是,沒有數學過程可以讓您獲取該結果字元串並找出原始輸入是什麼。

讓我們以 MD5 作為散列函式的範例。如果我對字元串“password”執行 MD5,我將始終得到結果“5f4dcc3b5aa765d61d8327deb882cf99”。但是,如果您只是給某人一個結果字元串(“5f4d …”),他們就不可能應用一些數學過程來“反轉”函式並找出它來自“密碼”。

這意味著當使用者第一次設置他們的密碼時,您對其應用雜湊函式並儲存結果。因此,不是儲存“密碼”,而是儲存“5f4dcc3b5aa765d61d8327deb882cf99”。然後,當該使用者嘗試登錄時,您將輸入他們在登錄表單上的密碼框中輸入的任何內容,並應用相同的散列函式。如果您得到的結果與數據庫中儲存的結果相同,那麼他們一定輸入了與最初選擇的密碼相同的密碼,即使您不知道原始密碼實際上是什麼。

現在,即使不可能“反轉”散列函式,但相同的輸入總是給出相同的輸出這一事實意味著某人可以簡單地建立一個輸入/輸出對的大型數據庫,並使用它來有效地反轉散列。這被稱為“彩虹表”。網際網路上有很多可用的方法,因此使用簡單的散列是不安全的,以防萬一您的數據庫受到損害。也就是說,即使在數學上不可能取“5f4dcc3b5aa765d61d8327deb882cf99”並確定它來自在“密碼”上執行 MD5,但在實踐中很容易確定。您所要做的就是通過 MD5 執行字典中的每個單詞並儲存結果,並且您可以輕鬆地反轉簡單的密碼。

這就是“加鹽”的用武之地。如果您為每個使用者生成一個隨機的“鹽”字元串並將其附加到他們的密碼中,它實際上會破壞彩虹表。例如,假設上面的同一使用者使用密碼作為“密碼”註冊。在散列之前,我們生成一個隨機的 8 個字元的鹽附加到他們的密碼上。假設它是“A4BR82QX”。現在,我們不是散列“密碼”,而是散列“A4BR82QXpassword”。這給出了結果“87a4ba071c8bcb5efe457e6c4e6c4490”,因此我們將其與鹽字元串一起儲存在數據庫中。然後,當該使用者嘗試登錄時,我們不會直接對他們在登錄表單中輸入的密碼進行散列和比較,而是將他們輸入的內容,再次放在“A4BR82QX”前面,然後對其進行散列。

實際上,您在這裡所做的是使預先生成的彩虹表對於嘗試破解數據庫中的密碼毫無用處。由於鹽是隨機的,並且每個使用者(通常)都有不同的鹽,因此攻擊者將不得不為每個單獨的使用者重新生成他們的彩虹表。這要困難得多。

但是,還有一個問題,那就是生成 MD5 雜湊值很快。儘管像這樣的加鹽需要他們重新生成彩虹表,但由於 MD5 的速度有多快,一些體面完整的彩虹表可以非常快速地創建。因此,如果他們只是想在您的網站上破解一個高價值帳戶,他們花一些時間生成彩虹表來嘗試反轉該密碼並不是什麼大不了的事。如果高價值賬戶的原始密碼本身不夠安全,即使加鹽也能很快找到。

所以下一步是找到一個散列函式,並使用它來代替像 MD5 這樣的快散列函式。讓您的網站多花幾秒鐘時間來檢查登錄並不是什麼大問題。但是當有人試圖生成彩虹表來破解密碼時,讓每個條目花費幾秒鐘是絕對的殺手鐧。我在這裡寫得夠多了,所以我將通過連結到這篇文章來結束,這篇文章詳細介紹瞭如何選擇一個好的、緩慢的散列函式:彩虹表足夠了:你需要知道的關於安全密碼方案的知識。

這是一個相當大的答案,如果有任何不清楚的地方,請在評論中告訴我,我會編輯詳細說明。

引用自:https://stackoverflow.com/questions/883371