我需要在(最好是文本)文件中存储和加密密码,以后我需要能够解密。密码用于我使用的其他服务,需要以明文形式(通过SSL)发送。这不是我可以改变的。这方面的最佳做法是什么?如何从恶意用户那里获得一定程度的密码保护?
我的平台是使用C#/ .NET 3.5的WinForms。
感谢。
答案 0 :(得分:13)
我假设您要加密密码,因为它将在用户计算机上,并且他们(可能)能够找到并使用它?如果是这样你基本上搞砸了 - 无论你做什么,因为它在用户域中,他们将能够得到它并找出加密并获得加密的密码(记住使用Reflector - 它的克隆 - isn “大多数人无法接触”并解密它们并且拥有它。简而言之,您所做的只是模糊密码,而不是保护密码。
我建议将其移出用户控件。例如,建立一个与客户端通信的Web服务,并在请求时安全地返回密码。这也允许您在将来需要时更改密码,并为您提供验证合法用户的方法。
答案 1 :(得分:7)
为什么需要解密密码?通常存储并比较密码的盐渍哈希。如果您加密/解密密码,则再次将密码作为纯文本,这很危险。如果某些用户具有相同的密码,则应该使用哈希值来避免重复哈希。对于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);
您可以计算密码的盐渍哈希并将其存储在您的文件中。在身份验证期间,您再次从用户条目计算哈希值,并将此哈希值与存储的密码哈希值进行比较。 因为从哈希中获取纯文本应该是非常困难的(从来都不是时间问题),密码不会再被作为纯文本阅读。
提示:切勿存储或发送未加密的密码。如果您获得了新密码,请尽快加密!
答案 2 :(得分:6)
System.Security.Cryptography.ProtectedData使用一些Windows API来加密数据,只有它知道的密码。
可能的一个用途是使Windows服务实际上执行需要密码的操作。用户与之交互的应用程序通过远程处理或WCF调用服务。只要服务使用DataProtectionScope.CurrentUser和服务用户与登录用户不同,密码就应该非常安全。
当然,这假定用户以无限修改服务或运行程序作为服务用户的有限用户身份运行。
答案 3 :(得分:2)
因为您使用的是WinForms和.Net,所以您的代码将在MSIL中可见 - 即使进行了模糊处理,因此您的解密代码也可见。
您是否想要隐藏密码?应用程序的用户不应该知道密码吗?
我认为你需要做一些用户验证,我很想把密钥放在一个单独的数据库中进行解密,并提供一些其他机制来解决这个问题。这样你就可以从winforms app中获取解密代码。
我还建议使用单独的服务来定期更改加密解密密钥并更新数据库中的所有密码。
答案 4 :(得分:1)
如果必须将其存储在文本文件中,则在AES中加密。
AES在c#
中被称为Rijndaelhttp://www.obviex.com/samples/Encryption.aspx
更好的地方是注册表,因为它可以保护机器的其他用户使用它。
仍然不是最好将其存储在用户可能能够到达的任何地方是危险的1/2方面的开发人员可以在反射器中加载您的应用并找到您的密钥。
或者有其他人建议的System.Security.Cryptography.ProtectedData。
您在计算机上可以做的最好的事情是创建一个证书,并加密/解密,并在计算机的密钥库中加载和锁定它。 (仍然需要处理代码中的证书密码)
答案 5 :(得分:1)
我刚刚实现了这样的东西来存储用户提供的密码。我将加密结果转换为基本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;
}
}
答案 6 :(得分:0)
不要将密码存储为代码的一部分。除了反编译和通过默默无闻的安全性问题,如果您更改密码,您需要重新编译和重新分发您的应用程序。
将密码存储为Web服务或应用程序有权访问的数据库。您正在通过网络与服务进行通信,因此您将完全连接到您。
答案 7 :(得分:0)
最重要的一点是文件的权限。即使内容是加密的,您也需要确保只有需要访问该文件的进程才能读取它。
答案 8 :(得分:0)
由于您必须通过网络以未加密的形式发送密码,因此您无法100%保护密码。
如果你需要在本地存储,AES就足够了,谈论痉挛,网络嗅探器等不是特别好的反对论,因为可以用任何程序完成同样的事情(当然,ASM比CIL更难,但它是一个小点)。
此类密码保护足以防止随意提取,而不是阻止专业人员解密。