Encrypting .NET configuration file

by Jimmy 9. April 2013 16:10

Did you know that .NET allows encrypting any section of the .config file? It can be either a section within web.config or app.config files or in any of linked files such as confirmit.config etc. A very useful feature if you want to protect passwords or other secret data.

The best of all is that your application will work unaffected if you encrypt configuration file. There is no code change required. You can work in your development environment with plain configuration and encrypt it when released. .NET will decrypt configuration transparently. This functionality is basically provided by the ASP.NET but you can use it outside web environment as well.

Recently I had to do it at work and, as I haven’t done that for ages now, it took me a moment to figure out all bits and bobs. For your entertainment and my memory here is how to do it.

Creating encryption key file

First, you will need to create a new RSA container to use later. Simply use the following command:

aspnet_regiis.exe -pc "MyKey"–exp

MyKey   Name of the key container. This should be later used in the configProtectedData element.
-exp    Creates the key as exportable. This option is required if you will want to share the same key between multiple servers.  

Now you can export the key to a xml file using the following command:

aspnet_regiis.exe -px "MyKey" keys.xml -pri

MyKey       Name of the key container. This should be later used in the configProtectedData element.
keys.xml    File where the key will be exported to.
-pri        Ensures the private key will be exported as well. This is required to encrypt configuration section.                

Encrypting in a web application

I will start with the ASP.NET application where things are nice and easy.

First you need an XML file with the encryption key you generated just moment ago. You can also use a key file provided by someone else.

The encryption process requires two preparation steps if the configuration section you are encrypting is a custom section that is declared in the configSections element of the .config.

Firsly, the aspnet_regiis.exe will have to be able to load the assembly that defines the section. You can either put it in the GAC or simply copy to the same folder as aspnet_regiis.exe. If you fail to do so you will get an error. After you finish encryption you can delete this assembly.

Lastly you need to ensure the section declaration contains both type and assembly name, i.e.

<section name="mySection" type="MyApp.MySection, MyApp.Configuration" />

Having that done you are ready to roll.

The first step is to add the following section to your config file

<configProtectedData> 
  <providers> 
    <add  keyContainerName="CustomKeys"
          useMachineContainer="true"
          description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
          name="CustomProvider"
          type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> 
  </providers> 
</configProtectedData> 

The name you specify in the keyContainerName and name attributes will be used later.

If you generated your own key you can skip this command, otherwise if you received the key from someone else you need to import it. The below command will import the key to the container.

aspnet_regiis.exe -pi CustomKeys keys.xml

CustomKeys    The key container name as defined in the configProtectedData before.
keys.xml      Path to the xml file with the encryption key.     

Having the key in the container you can now start encrypting. To encrypt a section use this command:

aspnet_regiis.exe -pef section –site SiteName -app /VirtualPath -prov CustomProvider

section           The name of the section element you want to encrypt.
SiteName          The site name if the application is configured in a specific IIS site. This parameter can be omitted if the application is in the IIS default web site.
/VirtualPath      Virtual path to the website. It must start from the “/” character.
CustomProvider    Name of the provider as defined in the configProtectedData element before.

Finally you need to grant permissions for the application pool user to the specific key container. You can do it using:

aspnet_regiis.exe -pa "CustomKeys" UserName

CustomKeys    The key container name as defined in the configProtectedData element.
UserName      The web site application pool user name.        

And that’s it. Now your config section has been encrypted. The cool thing is that aspnet_regiis.exe is clever enough to figure out if the section is in the web.config or some side .config file. You can also encrypt all config files in a specific folder and more. For more information see MSDN documentation http://msdn.microsoft.com/en-us/library/k6h9cz8h(v=vs.80).aspx and http://msdn.microsoft.com/en-us/library/53tyfkaw(v=vs.100).aspx.

What about non-web application?

The above method will only work for web application. For all other applications you will have to use a workaround.

Sometimes you may have a non-web application, i.e. service and corresponding web application. Both applications may share certain parts of the configuration. In that case you can just do required changes in the app.config and then copy encrypted sections from your web application. The only thing left to do will be to grant permissions to the key container as your application will likely work under another user than the IIS app pool.

If you have totally independent application however, then your case is a bit more complex. What you can do is to create an empty web application, copy all configs, encrypt them and then copy back to your application. A bit fiddly way but it should work.

Sharing keys between servers

You also may want to share the same key between multiple servers. This may be desired in load balancing scenarios where configuration is centrally propagated. In such case you should encrypt required configuration sections on one machine and then import the encryption key on other servers where the encrypted configuration will be used.

To import the key file you will need to copy the key XML file to each server and run the following command:

aspnet_regiis.exe -pi "MyKey" keys.xml

MyKey       Name of the key container. This should be later used in the configProtectedData element.
keys.xml    File containing the encryption key.

Happy encrypting.

HTH

Tags: , , ,

Coding | Security

blog comments powered by Disqus