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
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.
System.Security.Cryptography.ProtectedData in the System.Security assembly uses some Windows APIs to encrypt data with a password only it knows.
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.
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.
Encrypted in AES if you must store it in a text file.
AES is better known as Rijndael in c#
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.
Or there is System.Security.Cryptography.ProtectedData that someone else suggested.
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)
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.
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.
I would also suggest a separate service which runs to regularly change the encryption decryption keys and updates all passwords in the database.
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.
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.
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;
}
}
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!