加密和解密密码的最佳实践?(C#/.NET)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/785016/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Best practices for encrypting and decrypting passwords? (C#/.NET)
提问by Eyvind
I need to store and encrypt a password in a (preferably text) file, that I later need to be able to decrypt. The password is for another service that I use, and needs to be sent there in clear text (over SSL). This is not something I can change. What are best practices in this area? How can achieve some degree of protection of the password from malicious users?
我需要在(最好是文本)文件中存储和加密密码,我以后需要能够解密。密码用于我使用的另一项服务,需要以明文形式(通过 SSL)发送到那里。这不是我能改变的。这方面的最佳做是什么?如何在一定程度上保护密码免受恶意用户的侵害?
My platform is WinForms with C#/.NET 3.5.
我的平台是带有 C#/.NET 3.5 的 WinForms。
Thanks.
谢谢。
回答by Sam Meldrum
Because you are using WinForms and .Net, your code is going to be visible in MSIL - even if obfuscated, and therefore your decryption code is visible.
因为您使用的是 WinForms 和 .Net,您的代码将在 MSIL 中可见 - 即使被混淆,因此您的解密代码是可见的。
Who are you trying to hide the password from? Is the user of the app not supposed to know the password?
你想向谁隐藏密码?应用程序的用户不应该知道密码吗?
I think you are going to need to do some user validation, and I would be tempted to put keys to the decryption in a separate database and provide some other mechanism to get that out which should require authentication. That way you can get the decryption code out of the winforms app.
我认为您将需要进行一些用户验证,并且我很想将解密的密钥放在一个单独的数据库中,并提供一些其他机制来解决需要身份验证的问题。这样你就可以从 winforms 应用程序中获取解密代码。
I would also suggest a separate service which runs to regularly change the encryption decryption keys and updates all passwords in the database.
我还建议使用单独的服务来定期更改加密解密密钥并更新数据库中的所有密码。
回答by Robert MacLean
I am assuming that you want to encrypt the password as it will be on the users machine and they will (possibly) be able to find it and use it? If so you are basically screwed - no matter what you do, since it is in the users domain they will be able to get it and figure out the encryption and get the password for the encryption (remember that using Reflector - and it's clones - isn't out of the reach of most) and decrypt it and they have it. In short all you are doing is obfuscating the password, not securing it.
我假设您想对密码进行加密,因为它将在用户计算机上使用,并且他们(可能)能够找到并使用它?如果是这样,你基本上被搞砸了 - 无论你做什么,因为它在用户域中,他们将能够获得它并找出加密并获得加密密码(请记住,使用 Reflector - 它是克隆 - 是不是大多数人接触不到的)并解密它,他们就拥有它。简而言之,您所做的只是混淆密码,而不是保护密码。
What I would recommend is actually move it out of the users control. For example put up a web service which communicates with the client and returns the password securely when requested. This also allows you to change the password, if needed in future as well as provides you with a way to validate legitimate users.
我建议实际上将其移出用户控制范围。例如,建立一个与客户端通信并在请求时安全返回密码的 Web 服务。这还允许您在将来需要时更改密码,并为您提供一种验证合用户的方。
回答by Chad Grant
Encrypted in AES if you muststore it in a text file.
如果您必须将其存储在文本文件中,则在 AES 中加密。
AES is better known as Rijndael in c#
AES 在 C# 中被称为 Rijndael
http://www.obviex.com/samples/Encryption.aspx
http://www.obviex.com/samples/Encryption.aspx
Better place would be the registry, since it would protect other users of the machine getting to it.
更好的地方是注册表,因为它可以保护机器的其他用户访问它。
Still not the best storing it anywhere that a user might be able to get to is dangerous a 1/2 way decent developer can load up your app in reflector and find your key.
仍然不是最好的将它存储在用户可能能够到达的任何地方是危险的,体面的开发人员可以 1/2 的方式在反射器中加载您的应用程序并找到您的密钥。
Or there is System.Security.Cryptography.ProtectedData that someone else suggested.
或者有其他人建议的 System.Security.Cryptography.ProtectedData 。
The best you could do on a machine is create a certificate and encrypt/decrypt with it loaded and locked down in the machine's keystore. (Still have to deal with the certificate password being in your code)
您可以在机器上做的最好的事情是创建一个证书并加密/解密它在机器的密钥库中加载和锁定。(仍然需要处理代码中的证书密码)
回答by Unsliced
Do not store the password as part of the code. Aside from the issues of decompilation and relying on security through obscurity, if you change the password you need to recompile and redistribution your application.
不要将密码存储为代码的一部分。除了反编译和通过默默无闻依赖安全性的问题之外,如果您更改密码,您需要重新编译和重新分发您的应用程序。
Store the password as a webservice or in a database that the application has access to. You're communicating with a service over the web, so you will be connected, after all.
将密码存储为 Web 服务或应用程序有权访问的数据库中。您正在通过网络与服务进行通信,因此您终将保持联系。
回答by Dave Webb
One of the most important thing is the permissions on the file. Even if the content is encrypted you need to make sure that only the processes that need access to the file can read it.
最重要的事情之一是文件的权限。即使内容被加密,您也需要确保只有需要访问文件的进程才能读取它。
回答by Austin
System.Security.Cryptography.ProtectedDatain the System.Security assembly uses some Windows APIs to encrypt data with a password only it knows.
System.Security 程序集中的 System.Security.Cryptography.ProtectedData 使用一些 Windows API 使用只有它知道的密码来加密数据。
One possibly use of this would be to have a Windows service that actually does the operation requiring the password. The application that the user interacts with calls into the service via remoting or WCF. As long as the service used DataProtectionScope.CurrentUser and the service user is different from the logged on user, the password should be pretty safe.
一种可能的用途是让 Windows 服务实际执行需要密码的操作。用户与之交互的应用程序通过远程处理或 WCF 调用服务。只要服务使用了 DataProtectionScope.CurrentUser 并且服务用户与登录用户不同,密码应该是非常安全的。
This of course assumes that the users are running as limited users who cannot modify the service or run program as the service's user.
这当然假设用户以受限用户身份运行,他们不能以服务用户身份修改服务或运行程序。
回答by Enyra
Why you need to decrypt the password? Usually a salted hash of the password is stored and compared. If you encrypt/decrypt the password you have the password as plain text again and this is dangerous. The hash should be salted to avoid duplicated hash if the some users have the same passwords. For the salt you can take the user name.
为什么需要解密密码?通常存储和比较密码的加盐散列。如果您加密/解密密码,您将再次获得纯文本密码,这很危险。如果某些用户具有相同的密码,应该对散列进行加盐以避免重复散列。对于盐,您可以使用用户名。
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);
You can calculate the salted hash of the password and store that within your file. During the authentication you calculate the hash from the user entries again and compare this hash with the stored password hash. Since it should be very difficult (its never impossible, always a matter of time) to get the plain text from a hash the password is protected from reading as plain text again.
您可以计算密码的加盐哈希并将其存储在您的文件中。在身份验证期间,您再次根据用户条目计算散列,并将此散列与存储的密码散列进行比较。由于从散列中获取纯文本应该非常困难(永远不可能,总是时间问题),因此密码受到保护,不会再次作为纯文本读取。
Tip: Never store or send a password unencrypted. If you get a new password, encrypt is as soon as possible!
提示:切勿存储或发送未加密的密码。如果您获得新密码,请尽快加密!
回答by majkinetor
Since you must send the password in unencrypted form over the network, there is nothing you can do to protect it 100%.
由于您必须通过网络以未加密的形式发送密码,因此您无100% 保护它。
AES is good enough if you need to store locally, and talking about disasms, network sniffers etc is not particulary good contra-argument becuase the same thing can be done with anyprogram (sure, ASM is harder then CIL but its a minior point).
如果您需要在本地存储,AES 就足够了,并且谈论 disasms、网络嗅探器等并不是特别好的反驳,因为任何程序都可以做同样的事情(当然,ASM 比 CIL 更难,但它是一个小点) .
Such password protecting is good enough to prevent casual pick up, not to prevent decoding by proffesionals.
这样的密码保护足以防止随意窃取,而不是防止专业人士解码。
回答by Chris Ostler
I just implemented something like this for storing a user supplied password. I converted the encrypted result to a base 64 encoded string, so that I could easily store it in my application's user settings.
我刚刚实现了这样的东西来存储用户提供的密码。我将加密结果转换为 base 64 编码的字符串,以便我可以轻松地将它存储在我的应用程序的用户设置中。
From your question, it seems that your malicious user is actually using your application, so this will only provide obfuscation. Though no key would be revealed through the use of Reflector, the plain text would be visible in a debugger.
从您的问题来看,您的恶意用户似乎实际上正在使用您的应用程序,因此这只会提供混淆。尽管使用 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;
}
}