Best way to store encryption keys in .NET C#

65,968

Solution 1

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.

Solution 2

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

Solution 3

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).

Solution 4

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.

Solution 5

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.

Share:
65,968
ganeshran
Author by

ganeshran

Updated on July 05, 2022

Comments

  • ganeshran
    ganeshran almost 2 years

    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?

  • Wowa
    Wowa over 13 years
    DPAPI can also easy hacked after decompiling
  • user1149201
    user1149201 over 13 years
    @Wowa: decompiling of what: your program? And then you can see that the application uses the DPAPI. This still does not allow to decrypt when you do not have the keys from the user.
  • ganeshran
    ganeshran over 13 years
    I thought the key and IV had to be constant for decryption and encryption. Can the iv change and the text is still decryptable? I guess I need to do more reading into this.
  • user1149201
    user1149201 over 13 years
    You need to same IV to encrypt and decrypt, but it is not a secret like the key. So you can generate a different IV with every encryption run, and give the IV to the receiver. The easiest is to put the IV before the encrypted content. Creating a new IV with every run, will make it more difficult to find your key.
  • Hossein Shahdoost
    Hossein Shahdoost over 8 years
    What if we have predefined configurations? (like connectionString) do we have to encrypt the config file on the target machine?
  • Wjdavis5
    Wjdavis5 about 8 years
    @HosseinShahdoost If you use dpapi, and you have active directory setup, you can protect the config with that user and that user can decrypt it on any machine they sign into.
  • Hossein Shahdoost
    Hossein Shahdoost about 8 years
    @Wjdavis5 Thankx for your info but what if they don't have AD?
  • Wjdavis5
    Wjdavis5 about 8 years
    @hossein what if they don't? You can still use dpapi.
  • Wjdavis5
    Wjdavis5 about 8 years
    @Wowa how does decompiling the code help you hack dpapi?
  • iamjayp
    iamjayp almost 7 years
    You are correct. But, we still can recover the key as it stays in the memory of computer that is RAM. It is still not an applicable method to protect the key. Also http is not secure.
  • iamjayp
    iamjayp almost 7 years
    Creating a new key for each user would not be a practical way to protect the key
  • Mario Levrero
    Mario Levrero almost 7 years
    This would not work in a multiserver environment, right?
  • Muhammad Ummar
    Muhammad Ummar over 4 years
    Pretty old question but one thing I couldn't understand is e.g. I want to store some predefined AES keys in my code (constant), the thing is it will be part of my source code, then protecting them doesn't make sense to me, because if some one de-compile then the AES keys would be visible. Am I missing something here? Or the storing part would be outside my application like in installer?
  • badjuice
    badjuice about 2 years
    @GvS since this classes uses the DPAPI from Windows it is worth mentioning that this solution is not useful for other platforms.