2011-06-28 154 views
2

我發現了一些在線代碼,對於我正在嘗試做的工作相當不錯。我需要一些能夠加密密碼,將其保存到數據庫並輕鬆檢索的東西。下面的代碼幾乎可以處理我所尋找的任何事情。C#密碼加密

 string UserName = txtUser.Text; 
     string password = txtPass.Text; 

     string encrKey = "keyvalue"; 
     byte[] byteKey = { }; 
     byte[] IV = {25, 47, 60, 88, 99, 106, 125, 139}; 
     byteKey = Encoding.UTF8.GetBytes(encrKey.Substring(0, 8)); 
     DESCryptoServiceProvider des = new DESCryptoServiceProvider(); 
     byte[] inputArray = Encoding.UTF8.GetBytes(password); 

     MemoryStream ms = new MemoryStream(); 
     CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(byteKey, IV), CryptoStreamMode.Write); 
     cs.Write(inputArray, 0, inputArray.Length); 
     cs.FlushFinalBlock(); 
     password = Convert.ToBase64String(ms.ToArray()); 

     SqlCommand cmd = new SqlCommand("INSERT INTO USers (UserName, Password) VALUES (@UserName, @Password)", myConnection); 
     cmd.CommandType = CommandType.Text; 

     cmd.Parameters.AddWithValue("@UserName", UserName); 
     cmd.Parameters.AddWithValue("@Password", password); 

     SqlDataReader rdr = cmd.ExecuteReader(); 

我遇到的問題是密碼爲8個字符或更長時的代碼錯誤。我得到這個錯誤:

System.Security.Cryptography.CryptographicException:指定的鍵不是此算法的有效大小。錯誤在Cryptostream行上生成。

我需要爲我的密鑰使用不同的類型嗎?

+0

的可能重複[醃製密碼:最佳實踐(HTTP://計算器。com/questions/674904/salting-your-password-best-practices) –

回答

14

通常的做法不是加密數據庫中的密碼,而是對其進行散列。
當用戶嘗試登錄時,你需要輸入他的密碼,對其進行散列並與存儲在數據庫中的散列進行比較。

行業標準散列算法是SHA-1,它可以在.NET中讀取。

爲了獲得更高的安全性,您可以在散列中使用「Salt」。

你可以閱讀更多關於它在這裏:Salting Your Password: Best Practices?

+1

我嘗試了MD5並使其完美運行,但我無法弄清楚如何將數據庫中的哈希與登錄表單和忘記的密碼鏈接進行比較。 – Matt

+0

當你散列你的密碼時,你不能做一個「忘記你的密碼」來發送用戶他當前的密碼,而是你提供一個「重置我的密碼」。 – Variant

+0

SHA1比MD5更好,因爲MD5不再被認爲是安全的。 – Variant

0

試試這個:

var hash = Encoding.ASCII.GetBytes(password); 
var sha1 = new SHA1CryptoServiceProvider(); 
var sha1hash = sha1.ComputeHash(hash); 
var hashedPassword = Encoding.ASCII.GetString(sha1hash); 
+0

看到上面的帖子變種。 – Matt

+1

-1使用ASCII是一個**糟糕的主意。這意味着ASCII範圍之外的任何字符都是_ignored_!因此,僅由非ASCII字符組成的兩個完全不同的密碼將具有相同的散列! –

1

哈希密碼是加密相比要好得多。您將密碼的散列存儲在數據庫中,並且不再關心普通文本密碼。當用戶登錄時,您獲取普通文本密碼,對其進行散列並對兩個散列(即數據庫中的散列和散列在用戶輸入中的散列)進行身份驗證。這裏明確的好處是,你確保沒有人 - 無論爲什麼他訪問數據庫 - 將知道原始密碼(理論上)。

2

如果你需要真正扭轉加密,只需使用ProtectedData類: http://msdn.microsoft.com/en-us/library/system.security.cryptography.protecteddata.aspx

如果其他人在這裏是正確的,用鹽醃哈希值,如下面的例子類。以下取自「Another example of how to store a salted password hash

public sealed class PasswordHash 
{ 
    const int SaltSize = 16, HashSize = 20, HashIter = 10000; 
    readonly byte[] _salt, _hash; 
    public PasswordHash(string password) 
    { 
     new RNGCryptoServiceProvider().GetBytes(_salt = new byte[SaltSize]); 
     _hash = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize); 
    } 
    public PasswordHash(byte[] hashBytes) 
    { 
     Array.Copy(hashBytes, 0, _salt = new byte[SaltSize], 0, SaltSize); 
     Array.Copy(hashBytes, SaltSize, _hash = new byte[HashSize], 0, HashSize); 
    } 
    public PasswordHash(byte[] salt, byte[] hash) 
    { 
     Array.Copy(salt, 0, _salt = new byte[SaltSize], 0, SaltSize); 
     Array.Copy(hash, 0, _hash = new byte[HashSize], 0, HashSize); 
    } 
    public byte[] ToArray() 
    { 
     byte[] hashBytes = new byte[SaltSize + HashSize]; 
     Array.Copy(_salt, 0, hashBytes, 0, SaltSize); 
     Array.Copy(_hash, 0, hashBytes, SaltSize, HashSize); 
     return hashBytes; 
    } 
    public byte[] Salt { get { return (byte[])_salt.Clone(); } } 
    public byte[] Hash { get { return (byte[])_hash.Clone(); } } 
    public bool Verify(string password) 
    { 
     byte[] test = new Rfc2898DeriveBytes(password, _salt, HashIter).GetBytes(HashSize); 
     for (int i = 0; i < HashSize; i++) 
      if (test[i] != _hash[i]) 
       return false; 
     return true; 
    } 
} 
1

我建議你使用bcrypt。源代碼可在http://code.google.com/p/bcryptnet/ 下載並使用它。但在使用之前。閱讀文檔並理解它是如何工作的以及爲什麼要加密... 這很重要。

通過我的研究數週密碼加密。我終於找到了最適合我需要的bcrypt。 (我認爲這是最適合的密碼,糾正我,如果我錯了)

它是一種單向加密。就像少數程序員所說的一樣,將其散列並比較但不解密。

希望這對你有所幫助。如果你發現othre有趣的事情,請讓我知道XD和平~~

什麼,我說的不對,大家指正XD