Encrypting string in an external config for ASP.NET


I have seen this type of question a lot lately:
 
 
The bad news is I do not have an answer. I have tried all variations of aspnet_regiis to no avail. The good news is there is an answer, if you think outside the box.
 

The Set Up

The setup for this is easy. I have a website that I want to encrypt the connection strings in. I have placed them in an external file. The files look somehting like this:

web.config

  <connectionStrings configSource="db.config"></connectionStrings>

db.config

<connectionStrings>
    <add key="MyConnectionString" connectionString="{something}"/>
<connectionStrings>

You will have to supply your own {something} here, as these are your strings. Open-mouthed

The following will work:

aspnet_regiis -pe "connectionStrings" -app "/MyWebSite"

as long as the connection strings are in the web.config, but the following does nothing:

aspnet_regiis -pef "connectionStrings" C:projectswebsitesMyWebSitedb.config

Not quite true, as it errors out, which is something. What to do?

Solution

The answer is fairly simple. Encrypt in the web.config and then move the connectionStrings section to the db.config file. You can do this with the standard aspnet_regiis. Make a copy of the config section before you do this, just so you have a backup (sometimes decryption is problematic).

Here is one way to set up a tool to do this for you.

  1. Create an application. In this case, I am using a web app to encrypt another web app, but it can be other forms of app. I am just showing off, perhaps?
  2. On the form of the app, drop two textboxs and a button (we can make this more full featured by querying IIS for sites, if you like, and use a drop down)
  3. Double click the button and add the following code to the button event handler

    Configuration config = WebConfigurationManager.OpenWebConfiguration("/" + websiteTextBox.Text);
    ConfigurationSection section = config.GetSection(sectionTextBox.Text)
     if (!section.SectionInformation.IsProtected)
            {
                section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                config.Save();
            }

  4. Run the page and type in the name of the web. If you want to make this more sexy, you might want to add a dropDown for the protection provider, as not everyone wants "DataProtectionConfigurationProvider", but this is just a simple example

The resulting config looks something like this (albeit with a much longer cipherValue – bolded section):

<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
  <EncryptedData>
    <CipherData>
      <CipherValue>AQAAANC … houZY5ihx4v2Q==</CipherValue>
    </CipherData>
  </EncryptedData>
</connectionStrings>

Now copy this to the external file and change the config to point to it (as above). I have repeated the section that goes in the web.config below:

<connectionStrings configSource="db.config"></connectionStrings>

Want to test it? Add a web page to the web site with the following Page_Load:

    protected void Page_Load(object sender, EventArgs e)
    {
        string connString = ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
        Response.Write(connString);
    }

If you see the connection string on the page, all is set up correctly.

It would be nice if you could simply encrypt any file, but I think I know the reason this is not so. In some instances, you encrypt using your own keys. It is possible, for example, to encrypt some items in your web using a key specified in the web.config. In fact, this is often preferred for applications that reside on multiple machines. I do not say "Microsoft preferred" as duplication of machine keys is the more secure method, but it is a quick way to set up a simple web farm where every machine can decrypt.

Of course, the tool could be altered to work with both web.config and an external file, but this adds complexity to the scenario. Since you can work your way around the issue with an "out of the box" solution, like the one above, it is not a big deal.

Peace and Grace,
Greg

Leave a comment