.NET中如何安全地存儲認證信息(C#)
TODO: 本文由 赤石俊哉 翻譯整理,您可以將本文自由地用於學習交流。如需用於其他用途請徵得作者的同意。
原文鏈接:How to securely save username/password (local)? - StackOverFlow
驗證輸入的用戶名和密碼
如果你只希望驗證輸入的用戶名和密碼是否匹配,可以使用Rfc2898DerivedBytes
類(即PBKDF2
)。這比起使用諸如三次DES以及AES這樣的加密算法來說要更安全一些,因爲從RFC2898DerivedBytes
產生的結果逆推出密碼原文是不可行的。你只能將密碼轉換成PBKDF2
的結果。
你可以參考使用密碼的SHA1哈希值作爲密碼字符串推導加密祕鑰和向量的鹽,是否可行?,
這裏面有一個示例,也討論了在WinRT/Metro環境的.Net環境下C# Metro風格的密碼字符串加密解密。
存儲密碼
如果你希望存儲密碼以便以後進行復用,你可以使用Windows Data Protection API(DPAPI)
。
它是使用了操作系統生成並且保護的密鑰進行三次DES加密算法來加密解密信息的。
這就意味着你的應用程序可以省去一個大麻煩,那就是它不需要去關心密鑰如何去生成以及保護。
在C#
中,使用System.Security.Cryptography.ProtectedData
類。
舉個例子,使用ProtectedData.Protect()
加密一小段數據:
// 需要被保護的數據。使用Encoding.UTF8.GetBytes()將一個字符串轉換成byte數組。
byte[] plaintext;
// 生成一個附加的熵(用於向量的初始化)
byte[] entropy = new byte[20];
using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider()){
rng.GetBytes(entropy);
}
byte[] ciphertext = ProtectedData.Protect(plaintext, entropy, DataProtectionScope.CurrentUser);
安全地存儲熵值(entropy
)和加密後文本(ciphertext
),比如存儲在一個只有當前用戶具有讀寫權限的文件或者註冊表項內。
在程序中,需要訪問原始數據的時候,只需要使用ProtectedData.Unprotect()
:
byte[] plaintext = ProtectedData.Unprotect(ciphertext, entropy, DataProtectionScope.CurrentUser);
還有一些其他要注意的安全考慮,比如,避免直接將像密碼這類的隱私信息存儲爲一個字符串(string
),這樣做的話在內存中是不可被通知的,所以其他人要是查看程序的內存或者Dump內存的時候,就會看到密碼。
使用SecureString
或者一個byte數組來代替。在不需要使用密碼的時候,儘快釋放掉他們,或者是全部填寫0。