Developers often use the app.config (or web.config) file to hold database connection strings and application settings. For example:

<connectionStrings>
  <add name="WonderDb" connectionString="Server=BigServe1;Database=Wonder;Integrated Security=True" providerName="System.Data.SqlClient" />
</connectionStrings>
<appSettings>
  <add key="FtpUser" value="ariadne" />
  <add key="FtpPassword" value="maze1$" />
</appSettings>

You can find several pages on how to encrypt these settings, but they don’t usually show a typical solution, which, for me, includes:

  1. Encrypting/decrypting both connectionStrings and appSettings in one step.
  2. Doing it from code.
  3. Reduced parameters.

Granted, this is a simple case, where I don’t care about selectively encrypting settings. For that, Jon Galloway has a good post. In fact, we’ll use Jon’s post as our basis.

Important: In your project, you need to add the System.Configuration assembly. You also add using System.Configuration, but that by itself doesn’t include all the methods we need without referencing the assembly.

In my version, I removed the check for whether the section is locked, because I want an error thrown.

if (!section.ElementInformation.IsLocked)
{. . .
}

I also allow either encrypting or decrypting. Finally, I wrap up the default behavior, encrypting both appSettings and connectionStrings, in a single method call. Here’s the complete Console Application code.

using System;
using System.Configuration;

namespace EncryptConfig
{
    class Program
    {
        static void Main(string[] args)
        {
            SetDefaultConfigEncryption(true);
            Console.ReadLine(); //check the file, see if it’s encrypted.
        }

        private static void SetDefaultConfigEncryption(bool encrypt)
        {
            SetConfigSectionEncryption(encrypt,"appSettings");
            SetConfigSectionEncryption(encrypt, "connectionStrings");
        }

        private static void SetConfigSectionEncryption(bool encrypt, string sectionKey)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            ConfigurationSection section = config.GetSection(sectionKey);
            if (section != null)
            {
                if (encrypt && !section.SectionInformation.IsProtected)
                {
                        section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
                }
                if (!encrypt && section.SectionInformation.IsProtected)
                {
                        section.SectionInformation.UnprotectSection();
                }
                section.SectionInformation.ForceSave = true;
                config.Save(ConfigurationSaveMode.Full);
            }
        }
    }
}

Assuming an executable named EncryptConfig.exe, when running the above in Debug mode, the file that’s encrypted is bin\Debug\EncryptConfig.vshost.exe.Config

That’s nice and makes sense, because that’s the executable that’s actually in use, even though the regular exe has been built, too.The vshost config file is immediately reverted back when debugging ends. Here’s the encrypted version. Whew!

<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
        <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAtX6m55SoIUyvHb37ZhfgAAQAAAACAAAAAAAQZgAAAAEAACAAAAAkgsqGn6mo3noCKO2peA8w799u8ajWVLado9goQ8esSAAAAAAOgAAAAAIAACAAAADqB7GDKmDFY9buAJlgMDyUoos81ALB/3/UKAtk3wT53TADAAAHixr6r15/5eNFgPHnXPJD950sY5F9oAjYRF4Cpfu9sfd532WpEOxFnST1W4LgX+u+d8so2rf5FqN3ikxsJY4Y1p3xpQeJEA1xa4i9L4n5arPabK4mmNn7fKTKjxri1Xktqkhkb1FLV/opfFFRnOlRy64nFOzWr4Ucwwsr8VR7d3TTt6MD2Bg3pJDZiUgjcQ+tXdD8cHkEhfKfxbMdeLfO65uG6VbyAm+ldjp7p9D6c2Z9DyBbq+rEShrMvMTL+lZ52j9H63sD+V93ESJ9FMgjOMX48TG2ZvboQE6EbiLmM0uH50BqziGUat3ft3Frc+0mQHfoqhnVs2M7mCt5mkjE3Tb0pcvjN3XvWVqo9wy5jxB0K/9yRuPTtSdVBV1q4chHGUZ4XsvBjTnt67LP2XdAYcu/Xju6Swv/dkgXMuXPzuAMgizX86CYuLebR0hMNH3Spiz9ODX98wUFCJMzJ4kQupxpdRNafNKISQWZI7119Anjehz4x3yeWJjUNoatTMWxoQ2xeYr+SlyiRoTOI3BrvfPGgpkDG9nQH2S+8dWMJyWRPHBs2GbrPqjjtLA1yR+2rqt9Uocv29oBJ6DwvnT+FA0p9P/Qp91jzEpRmcTEz+EYoIJfwSsBOIZuRXllcNJkaO1Ni/ThvGpTg0aqotXrhY0MoQlI4m/iPly2qkKVKr3O1qMwY9GrYERTrbj5pKb+hXFPgsOAEDgRBiAHsH6FuoZjG0MIXVTGg4zmJ+7rhsa8EPh61ROI6DwW1rRTA9DSKs9LS1sxeHTR/8QWaLxZuRWSwjuZJaVybPyllU1rvOFzDY9Nv96wk1n9u6s21fSf233l4nuu+7np8VfUdYUxNGfn0TwH69bh8cg1wqaJVCEoSioMHFidrKArtSCciJHW27jn3/SsRz4HWNudebTY8WZTf9YsLTuP0jC7dxuX9CIpuhcJBXitpvyVGxwC5NfmKDAsl/Dws4Rt+/YXVJ/4j5JvT35ZxYbTm/cZgvhL/z6j5odkCkIxey3ulqt1o57VNWJ18Ks0lTStRN0esejDVL6ThnqSVtlP2BCB5bThoRGXvyxhuz6Y/ON4SgeK8vBAAAAAX9I6BKGWYUcUHSscMRV2a6VGisOj9FzqTTWn0YAbeQ2hK0ZuYgK2x7hgp6iZcFJnvvuvXWTHzdvDtEliixpHQQ==</CipherValue>
      </CipherData>
    </EncryptedData>
  </connectionStrings>
  <appSettings configProtectionProvider="DataProtectionConfigurationProvider">
    <EncryptedData>
      <CipherData>
        <CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAtX6m55SoIUyvHb37ZhfgAAQAAAACAAAAAAAQZgAAAAEAACAAAAAcT/dxC/l5+9h0pizxo4Thn6rgtJlRVLwGediRA8DpywAAAAAOgAAAAAIAACAAAADHdhTfi7lUXxm6CwB3S252W+lo63eEXsNwxrnPOdfQUCABAACM0LuV5c69abxGbAY6Btx9i/lUhfqjGd8B5MvNCmkwN9hQW90sPzgwBYc7o7EJPM9M2PrgbMXmCo1fUn45ZZdoL68b9andNZe78AJAKz+HNRPBaW3UD2ruwZMKr8F/FVlFxrVnrgytRxDbNNZGfwOR8WrfLsISJdOJHjZcOhLU+hsSVeA2WeSPoH/QR7L+zGqZ15/9VmULHK/0J2KacFKyqn8d4SNIOehAR+t7tlec/qdSsFYtsIWq+c4k4mgWWOVwhCXqzc+3dXRforeEYuBHfsG5KyYsxsaZZdg2dm3wooCJCCv8tK86FuDCBym8L5R1oreRWT8WAq73UM4GJn5in5ZDeAK00lnhjB8DddOy7GjrflIIM63Rc1ClXUrfm3lAAAAA+KiFbW8vRL7rF6Kl9uKDpVp8uzCMs5JcPM9lqHz5XNNQ3m7zEk8TaVoOLC56AKu5rJ+ecX76XYWfQqvpQxDj/g==</CipherValue>
      </CipherData>
    </EncryptedData>
  </appSettings>

There’s nothing new here, I just wanted to document what I think of as a common implementation instead of the generic one. If I’ve made a security error let me know.

References

Many pages reference David Hayden’s seminal post on the subject, but I was unable to locate the original.

https://msdn.microsoft.com/en-us/library/ms254494(v=vs.110).aspx
Jon Galloway’s Post
4 Guys from Rolla