我需要将密码存储和加密在一个(最好是文本)文件中,并且以后需要能够解密。该密码用于另一个我使用的服务,并需要明文(通过SSL)发送到该服务中。这不是我能改变的事情。在这方面有什么最佳实践?如何在一定程度上保护密码免受恶意用户的攻击?
我的平台是WinForms,使用C#/.NET 3.5。
谢谢。
我需要将密码存储和加密在一个(最好是文本)文件中,并且以后需要能够解密。该密码用于另一个我使用的服务,并需要明文(通过SSL)发送到该服务中。这不是我能改变的事情。在这方面有什么最佳实践?如何在一定程度上保护密码免受恶意用户的攻击?
我的平台是WinForms,使用C#/.NET 3.5。
谢谢。
我假设你想加密密码,因为它将保存在用户的机器上,他们可能会找到并使用它?如果是这样,无论你做什么都基本上束手无策,因为它在用户领域内,他们将能够获取它并解密密码(请记住,使用Reflector和它的克隆版本对大多数人来说并不困难)并得到它。简而言之,你所做的只是混淆密码,而不是保护它。
我建议的是将其移出用户的控制范围。例如,建立一个与客户端通信并在请求时安全返回密码的网络服务。这还使您有办法验证合法用户,并且如果需要在未来更改密码,也可以实现。
为什么需要解密密码?通常存储并比较的是密码的盐哈希值。如果加密/解密密码,则可以再次以明文形式获取密码,这是很危险的。哈希值应该被加盐以避免重复哈希,如果一些用户使用相同的密码,则可以使用用户名作为盐。
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.Cryptography.ProtectedData 在 System.Security 组件中使用一些 Windows API 以密码加密数据,仅它自己知道。
其中一个可能的应用是拥有一个实际执行需要密码的操作的 Windows 服务。用户交互的应用程序通过远程调用或 WCF 调用该服务。只要服务使用 DataProtectionScope.CurrentUser 并且服务用户与登录的用户不同,密码应该相对安全。
当然,这假设用户作为受限制的用户运行,无法修改服务或以服务用户身份运行程序。
我刚刚实现了一个类似的东西来存储用户提供的密码。我将加密结果转换为base64编码的字符串,以便可以轻松地将其存储在我的应用程序用户设置中。
从你的问题来看,似乎你的恶意用户实际上正在使用你的应用程序,所以这只会提供混淆。虽然通过使用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
更好的位置应该是注册表,因为它可以保护其他用户无法访问。
但是,将其存储在任何用户可能能够访问的地方仍然存在危险。一位相当不错的开发人员可以使用反编译工具加载您的应用程序并找到您的密钥。
或者,还有其他人建议使用 System.Security.Cryptography.ProtectedData。
在计算机上做得最好的事情是创建一个证书,并使用已加载和锁定在计算机密钥库中的证书进行加密/解密。(仍然需要处理代码中的证书密码)
不要将密码作为代码的一部分存储。除了反编译和依赖于安全性通过混淆之外,如果您更改密码,则需要重新编译和重新分发应用程序。
将密码存储为Web服务或应用程序可以访问的数据库中。毕竟,您正在通过网络与服务通信,因此您将保持连接。
其中最重要的事情之一是文件权限。即使内容已加密,您也需要确保只有需要访问该文件的进程才能读取它。
由于您必须以未加密的形式通过网络发送密码,因此无法百分之百地保护它。
如果您需要本地存储,则AES已足够好。关于反汇编、网络嗅探等方面的讨论并不是特别好的反驳观点,因为任何程序都可以做到这一点(当然,ASM比CIL更难,但这只是一个小问题)。
这种密码保护足以防止随意拾取,但无法防止专业人员的解码。