2011-06-14 69 views
6

我需要實現哈希(我不是指加密)來創建一些數據字段(密碼或一些細節,不需要以原始格式恢復,只需要在db中匹配)安全。你能否建議我實施哈希的最佳實踐?我將使用C#和SQL Server,它將成爲一個網站。實施哈希的最佳實踐?

+2

你能否提供更多細節?什麼數據字段,以及你從什麼保護他們? – 2011-06-14 01:32:36

+0

您需要提供更多信息,例如什麼樣的數據等 – mqpasta 2011-06-14 01:36:07

+1

確保您不會與加密混淆。當你散列一些東西時,你不能對它進行散列來獲取數據。散列主要用於根據提交的散列驗證內容,例如密碼等。 – Xhalent 2011-06-14 01:37:18

回答

5

OK,現在你說你保護,你有一些選擇的密碼。

NET框架有內建的算法 - MD5,SHA1,SHA2。 MD5和SHA1現在被認爲是過時和危險的,而不是堅持SHA256。

例如(從我的書取)

static byte[] GenerateSaltedHash(string password, byte[] salt) 
{ 
    byte[] plainText = Encoding.UTF8.GetBytes(password); 
    HashAlgorithm algorithm = new SHA256Managed(); 

    byte[] plainTextWithSaltBytes = 
    new byte[plainText.Length + salt.Length]; 

    for (int i = 0; i < plainText.Length; i++) 
    { 
    plainTextWithSaltBytes[i] = plainText[i]; 
    } 
    for (int i = 0; i < salt.Length; i++) 
    { 
    plainTextWithSaltBytes[plainText.Length + i] = salt[i]; 
    } 

    byte[] hash = algorithm.ComputeHash(plainTextWithSaltBytes);    
} 

現在的鹽是有停止哈希的預計算的查找(散列本身是不夠的任何更多的人有字典單詞,更預先計算哈希值)。但你如何得到一個鹽?那麼它是真正的唯一值,通常是隨機的一組字節。

public byte[] GenerateSalt(int length) 
    { 
     salt = new byte[length]; 

     // Strong runtime pseudo-random number generator, on Windows uses CryptAPI 
     // on Unix /dev/urandom 
     RNGCryptoServiceProvider random = new RNGCryptoServiceProvider(); 

     random.GetNonZeroBytes(salt); 

     return salt; 
    } 

所以你會打電話GenerateSalt(32)第一,得到鹽(32僅僅是一個例子,再如果你願意,你需要將鹽儲存旁邊的密碼 - 你不需要擔心保護它

最後,你需要一個比較函數,當你想檢查密碼時,你需要輸入用戶名,爲該用戶獲取salt,爲提供的密碼生成散列並存儲salt ,然後比較,你會這樣做使用類似

[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] 
public static bool ConstantCompare(byte[] array1, byte[] array2) 
{ 
    const byte Zero = 0; 
    int maxLength = array1.Length > array2.Length ? array1.Length : array2.Length; 
    bool wereEqual = array1.Length == array2.Length; 

    byte[] paddedArray1 = new byte[maxLength]; 
    byte[] paddedArray2 = new byte[maxLength]; 
    for (int i = 0; i < maxLength; i++) 
    { 
     paddedArray1[i] = array1.Length > i ? array1[i] : Zero; 
     paddedArray2[i] = array2.Length > i ? array2[i] : Zero; 
    } 
    bool compareResult = true; 
    for (int i = 0; i < maxLength; i++) 
    { 
     compareResult = compareResult & paddedArray1[i] == paddedArray2[i]; 
    } 
    return compareResult & wereEqual; 
} 

當然,我應該指出ASP.NET成員函數做salt和hash,所以它們應該是第一個調用點。如果別人已經完成了這項工作,那麼毫無意義。

+0

感謝@blowdart節省時間和寶貴的指導。 我還沒有使用ASP.net的成員函數和類。你能否多指導一下我應該看的東西呢? 謝謝 – user576510 2011-06-14 02:41:29

+0

哦,有一本關於ASP.NET會員資格數據庫的書,但基本上它會爲您註冊用戶註冊。您如何使用它取決於WebForms或MVC。 MSDN在http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx有關WebForms和http://www.asp.net/mvc/tutorials/authenticating-users-with-forms-authentication的介紹-cs有一個用於MVC – blowdart 2011-06-14 02:53:32

0

我想你誤會是什麼散列。您不使用散列來「使數據字段安全」,因爲散列只能在一個方向上計算。計算並存儲數據的散列,僅存儲散列,稍後將無法檢索數據。

您可能需要加密數據。這是一個完全不同的可以用它自己的一套問題蠕蟲:你如何存儲和保護的解密密鑰,使用何種加密算法,你做加密在數據庫級(SQL服務器支持)或應用程序級?您如何執行加密傳輸,並防止最終用戶複製數據?

+0

感謝@Joel,我對你解釋的散列和加密差異有同樣的想法。 我一直在尋找最佳實踐來實現哈希?像什麼算法應該使用?它應該在C#中還是在SQL Server中?任何其他的做法要遵循? – user576510 2011-06-14 02:10:00