簡體   English   中英

加密和解密密碼的最佳做法? (C#/。NET)

[英]Best practices for encrypting and decrypting passwords? (C#/.NET)

我需要在(最好是文本)文件中存儲和加密密碼,以后我需要能夠解密。 密碼用於我使用的其他服務,需要以明文形式(通過SSL)發送。 這不是我可以改變的。 這方面的最佳做法是什么? 如何從惡意用戶那里獲得一定程度的密碼保護?

我的平台是帶有C#/ .NET 3.5的WinForms。

謝謝。

我假設您要加密密碼,因為它將在用戶計算機上,他們(可能)能夠找到並使用它? 如果是這樣你基本上搞砸了 - 無論你做什么,因為它在用戶域中,他們將能夠得到它並找出加密並獲得加密的密碼(記住使用Reflector - 它的克隆 - isn “大多數人無法接觸”並解密它們並且擁有它。 簡而言之,您所做的只是模糊密碼,而不是保護密碼。

我建議的實際上是將其移出用戶控件。 例如,建立一個與客戶端通信的Web服務,並在請求時安全地返回密碼。 這也允許您在將來需要時更改密碼,並為您提供驗證合法用戶的方法。

為什么需要解密密碼? 通常存儲並比較密碼的鹽漬哈希。 如果您加密/解密密碼,則再次將密碼作為純文本,這很危險。 如果某些用戶具有相同的密碼,則應該使用哈希值來避免重復哈希。 對於salt,您可以使用用戶名。

HashAlgorithm hash = new SHA256Managed();
string password = "12345";
string salt = "UserName";

// compute hash of the password prefixing password with the salt
byte[] plainTextBytes = Encoding.UTF8.GetBytes(salt + password);
byte[] hashBytes = hash.ComputeHash(plainTextBytes);

string hashValue = Convert.ToBase64String(hashBytes);

您可以計算密碼的鹽漬哈希並將其存儲在您的文件中。 在身份驗證期間,您再次從用戶條目計算哈希值,並將此哈希值與存儲的密碼哈希值進行比較。 由於從哈希中獲取純文本應該非常困難(從來不是不可能,總是時間問題),因此密碼不會再被視為純文本。

提示:切勿存儲或發送未加密的密碼。 如果您獲得新密碼,請盡快加密!

System.Security程序集中的System.Security.Cryptography.ProtectedData使用一些Windows API來加密數據,只有它知道的密碼。

一個可能的用途就是擁有一個實際需要密碼操作的Windows服務。 用戶與之交互的應用程序通過遠程處理或WCF調用服務。 只要服務使用DataProtectionScope.CurrentUser和服務用戶與登錄用戶不同,密碼應該是非常安全的。

當然,這假定用戶以無限修改服務或運行程序作為服務用戶的有限用戶身份運行。

因為您使用的是WinForms和.Net,所以您的代碼將在MSIL中可見 - 即使進行了混淆,因此您的解密代碼也是可見的。

你是誰試圖隱藏密碼? 應用程序的用戶不應該知道密碼嗎?

我認為你需要做一些用戶驗證,我很想把密鑰放在一個單獨的數據庫中進行解密,並提供一些其他的機制來解決這個問題。 這樣你就可以從winforms應用程序中獲取解密代碼。

我還建議一個單獨的服務,它定期更改加密解密密鑰並更新數據庫中的所有密碼。

我剛剛實現了這樣的東西來存儲用戶提供的密碼。 我將加密結果轉換為基本64位編碼的字符串,以便我可以輕松地將其存儲在我的應用程序的用戶設置中。

從您的問題來看,您的惡意用戶似乎實際上正在使用您的應用程序,因此這只會提供混淆。 雖然通過使用Reflector不會顯示任何鍵,但是在調試器中可以看到純文本。

static byte[] entropy = { 65, 34, 87, 33 };

public string Password
{
    get
    {
        if (this.EncryptedPassword == string.Empty)
        {
            return string.Empty;
        }

        var encrypted = Convert.FromBase64String(this.EncryptedPassword);
        var data = ProtectedData.Unprotect(encrypted, entropy, DataProtectionScope.CurrentUser);
        var password = Encoding.UTF8.GetString(data);
        return password;
    }
    set
    {
        if (value == string.Empty)
        {
            this.EncryptedPassword = string.Empty;
            return;
        }

        var data = Encoding.UTF8.GetBytes(value);
        var encrypted = ProtectedData.Protect(data, entropy, DataProtectionScope.CurrentUser);
        var stored = Convert.ToBase64String(encrypted);
        this.EncryptedPassword = stored;
    }
}

如果必須將其存儲在文本文件中,請在AES中加密。

AES在c#中被稱為Rijndael

http://www.obviex.com/samples/Encryption.aspx

更好的地方是注冊表,因為它可以保護機器的其他用戶。

仍然不是最好的存儲在用戶可能到達的任何地方是危險的1/2方面體面的開發人員可以在反射器中加載您的應用程序並找到您的密鑰。

或者有其他人建議的System.Security.Cryptography.ProtectedData。

您在計算機上可以做的最好的事情是創建一個證書,並加密/解密它,並在機器的密鑰庫中加載和鎖定。 (仍然需要處理代碼中的證書密碼)

不要將密碼存儲為代碼的一部分。 除了反編譯和通過默默無聞的安全性問題,如果您更改密碼,您需要重新編譯和重新分發您的應用程序。

將密碼存儲為Web服務或應用程序可以訪問的數據庫。 您正在通過網絡與服務進行通信,因此您將完全連接到您。

其中一個最重要的是文件的權限。 即使內容已加密,您也需要確保只有需要訪問該文件的進程才能讀取它。

由於您必須通過網絡以未加密的形式發送密碼,因此您無法100%保護密碼。

如果你需要在本地存儲,AES就足夠了,談論痙攣,網絡嗅探器等不是特別好的反對論,因為任何程序都可以做同樣的事情(當然,ASM比CIL更難,但它是一個小點) 。

這種密碼保護足以防止隨意拾取,而不是防止專業人員解碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM