加密和解密密码的最佳实践?(C#/.NET)

加密和解密密码的最佳实践?(C#/.NET),c#,encryption,C#,Encryption,我需要在一个(最好是文本)文件中存储和加密一个密码,我以后需要能够解密这个文件。密码用于我使用的另一个服务,需要以明文形式(通过SSL)发送到那里。这是我无法改变的。这方面的最佳做法是什么?如何实现某种程度的密码保护,防止恶意用户使用 我的平台是WinForms和C#/.NET3.5 谢谢。因为您使用的是WinForms和.Net,所以您的代码在MSIL中是可见的-即使是模糊的,因此您的解密代码也是可见的 你想对谁隐藏密码?应用程序的用户不应该知道密码吗 我认为您将需要进行一些用户验证,我会尝试

我需要在一个(最好是文本)文件中存储和加密一个密码,我以后需要能够解密这个文件。密码用于我使用的另一个服务,需要以明文形式(通过SSL)发送到那里。这是我无法改变的。这方面的最佳做法是什么?如何实现某种程度的密码保护,防止恶意用户使用

我的平台是WinForms和C#/.NET3.5


谢谢。

因为您使用的是WinForms和.Net,所以您的代码在MSIL中是可见的-即使是模糊的,因此您的解密代码也是可见的

你想对谁隐藏密码?应用程序的用户不应该知道密码吗

我认为您将需要进行一些用户验证,我会尝试将解密的密钥放在一个单独的数据库中,并提供一些其他机制来进行验证,这需要进行身份验证。这样,您就可以从winforms应用程序中获取解密代码


我还建议使用一项单独的服务,定期更改加密解密密钥并更新数据库中的所有密码。

我假设您希望加密用户计算机上的密码,并且他们(可能)能够找到并使用它?如果是这样的话,你基本上是完蛋了——不管你做什么,因为它是在用户域中,他们将能够得到它,找出加密,并获得加密的密码(记住,使用反射器——以及它的克隆——并不是大多数人够不着的),然后解密,他们就拥有了它。简而言之,您所做的只是混淆密码,而不是保护密码


我的建议是将其移出用户的控制。例如,建立一个与客户机通信的web服务,并在请求时安全地返回密码。这还允许您在将来需要时更改密码,并为您提供验证合法用户的方法。

如果您必须将密码存储在文本文件中,则使用AES加密

AES在c中被称为Rijndael#


更好的地方应该是注册表,因为它可以保护机器的其他用户访问它

仍然不是用户能够到达的最佳存储位置是危险的,一个体面的开发人员可以通过1/2的方式在reflector中加载你的应用程序并找到你的密钥

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


在计算机上,您所能做的最好的事情就是创建一个证书,并在计算机的密钥库中加载和锁定证书进行加密/解密。(仍然需要处理代码中的证书密码)

不要将密码存储为代码的一部分。除了反编译和通过模糊性依赖安全性的问题外,如果更改密码,则需要重新编译和重新分发应用程序


将密码存储为Web服务或应用程序有权访问的数据库。您正在通过web与服务进行通信,因此您终究会被连接

最重要的一点是文件的权限。即使内容已加密,您也需要确保只有需要访问该文件的进程才能读取该文件。

在系统中。安全程序集使用一些Windows API使用只有它知道的密码加密数据

一个可能的用途是让Windows服务实际执行需要密码的操作。用户通过远程处理或WCF与服务调用交互的应用程序。只要服务使用的DataProtectionScope.CurrentUser和服务用户与登录用户不同,密码就应该非常安全


当然,这假设用户是以有限用户的身份运行的,不能修改服务或以服务用户的身份运行程序。

为什么需要解密密码?通常会存储并比较密码的盐散列。如果您对密码进行加密/解密,则密码将再次以纯文本形式显示,这是危险的。如果某些用户具有相同的密码,则应对哈希进行加密,以避免重复的哈希。对于盐,您可以使用用户名

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);
您可以计算密码的salt散列并将其存储在文件中。在身份验证过程中,再次从用户条目计算哈希值,并将此哈希值与存储的密码哈希值进行比较。 由于从散列中获取纯文本应该非常困难(这从来都不是不可能的,总是时间问题),因此密码将被保护,不会再次以纯文本形式读取


提示:切勿存储或发送未加密的密码。如果您获得新密码,请尽快加密

由于您必须通过网络以未加密的形式发送密码,因此您无法100%保护它

如果您需要在本地存储,AES就足够了,而谈论disasms、网络嗅探器等并不是特别好的相反论点,因为同样的事情可以通过任何程序来完成(当然,ASM比CIL更难,但它只是一个小问题)


这样的密码保护足以防止随意拾取,而不是阻止专业人员解码。

我刚刚实现了类似的方法来存储用户提供的密码。我将加密结果转换为base 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;
    }
}

“更好的地方应该是注册表,因为它可以保护机器的其他用户访问它。”将文本文件存储在注册表中不会影响其他用户的访问