70
votes

In our application we have a lot of sensitive configuration settings, which we are storing in a xml file which is again encrypted.

This secure file has to be decrypted in runtime and the configuration values read. but an issue arises that the key and initialization vector is hardcoded in the code and hence anyone can read it using Reflector.

What is the best way to store encryption keys in .NET so no one can read them using Reflector?

6
Is this a desktop application, or a web based one? If it's web based, is it distributed, or do you control the server?Paddy
You should also point the level of security you want. There are lots of ways to hide something and no less ways to get that from the hidden corner .)Ilya Dvorovoy
Maybe now RedGate are charging for Reflector it doesn't matter anymore.. ;-)Grant Crofton
@Paddy: Its a desktop application.ganeshran
What about storing the Key on a Hardware, here I am talking about Hardware Security Modules! Can we use it as best practices to hide the key? Can we store the key in configuration file and then encrypt the configuration file ? In my case I am talking about a Stand-alone .Net Application.iamjayp

6 Answers

23
votes

If you want to protect your data from other users. Take a look at the ProtectedData class.

(Disclaimer: Protecting your data to create a copy protection scheme is not covered in this answer).

This classes uses the DPAPI from Windows, to encrypt and decrypt data on user or machine level.

Using ProtectedData/DPAPI frees you from handling keys and securing the data yourself. And you can choose to protect the data for the current user. The data can be read from different computers, by the same domain users.

If you want create your own key. You can create a key per user/machine, and store this key in the registry. Because the registry can be secured, only the current user can read the key back. I know the registry has bad karma, but is actually very good at storing data like this.

PS: Do not put the IV in your code. Create a new IV every time, and put it in front of the data.

11
votes

You should use the Machine Keystore, it's a secure storage especially for this purpose. For example:

CspParameters cspParams = new CspParameters(PROV_RSA_FULL, null, KEYNAME);

cspParams.Flags = CspProviderFlags.UseMachineKeyStore;

RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParams);

Where KEYNAME is a custom string that can be used to retrieve the key later on.

For more examples, see this question: How to store a public key in a machine-level RSA key container

10
votes

If you can't read them in reflector, how do you expect the program to read them? You could obfuscate them by breaking them up and storing the parts all over the place, but (AFAIK) once you require your program to be able to read them, then anyone with access to your code can read them too.

Don't forget values in memory can be accessed as well (cough SecureString).

4
votes

Generally, a new key and IV should be created for every session, and neither the key nor IV should be stored for use in a later session.

To communicate a symmetric key and IV to a remote party, you would usually encrypt the symmetric key and IV using asymmetric encryption. Sending these values across an insecure network without encrypting them is extremely unsafe, as anyone that intercepts these values can then decrypt your data. For more information on this process of encrypting and transferring the key and IV, see Creating a Cryptographic Scheme.

3
votes

When you install the application, make a new set of RSA keys, then encrypt the data with AES using the private key as the password. As Windows stores RSA private keys securely on the PC that created them, the data can only be decrypted by the computer that created the data because only that computer will have the necessary key.

1
votes

What about storing the file encryption/decryption key on a remote server, getting it though a web service that would transfer it though https to the application? that way the key stay in the memory of the computer but is not into a source code file.

This requires to have connection to the key server by whoever runs the application though.