Introduction
In a certain cases, metadata embedded within your configuration file is sensitive. In fact, imagine that you develop an application that uses a data base as data source; all information about this data base is located in the configuration file. What if a hacker success to log into your configuration files and obtains the connection string and other metadata about your data base. It will be a catastrophe. To avoid such problems it is possible to encrypt data within the configuration file to render it more secure. In this article, I will give a trick of how to do that programmatically through a walkthrough.
Walkthrough
First, create and/or connect to a data base of your choice. For this walkthrough I will use an access data base with "C:\db.mdb" as full name.
I. Create a new windows application and name it EncryptConfigFile, Don't forget to add a reference to the System.Data.OleDb.
II. Now, go and select the project properties menu item under project menu

Figure 1
You do this in order to add some configuration settings into the configuration file. So select the settings tab, the following window appears:

Figure 2
Select a data base provider:

Figure 3
Then browse to the data base as follow:

Figure 4
Finally click OK

Figure 5
Now, browse to the application bin directory and open the configuration file

Figure 6
Witch looks like this
and has the same name as the exe file. Try to explore its contents:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
</configSections>
<connectionStrings>
<add name="EncryptConfigFile.Properties.Settings.Setting" connectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\bd.mdb"
providerName="System.Data.OleDb" />
</connectionStrings>
</configuration>
As you remark, the information about the data base connection is embedded within the connection strings tags. The problem here is that each person how has access to this configuration file could access to those metadata and may use them for malicious purposes.
In fact, there are two ways to encrypt configuration section within a configuration file, an easy one and a hard one:
The easy one:
The easy one is create a class with two statics methods as follow:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;
using System.Configuration;
using System.Windows.Forms;
namespace EncryptConfigurationFile
{
class ConfigurationSectionEncryptor
{
private ConfigurationSectionEncryptor() { }
/// <summary>
/// This static method helps encrypt the given data set
/// </summary>
/// <param name="ConfigurationFilePath">String : The configuration file path</param>
public static void Encrypt(string ConfigurationFilePath)
{
//Create a new ExeConfigurationFileMap
ExeConfigurationFileMap oFile = new ExeConfigurationFileMap();
//Precise its path
oFile.ExeConfigFilename = ConfigurationFilePath;
//Create a new configuration object related to the configuration file
Configuration oConfiguration = ConfigurationManager.OpenMappedExeConfiguration(oFile, ConfigurationUserLevel.None);
//Create a section and set it as the targeted section
ConnectionStringsSection oSection = oConfiguration.GetSection("connectionStrings") as ConnectionStringsSection;
//if the section is already encrypted dont ecrypt it again
if (oSection != null && !oSection.SectionInformation.IsProtected)
{
//The section ecryption
oSection.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
//Update the configuration file
oConfiguration.Save();
MessageBox.Show("Connection string encrypted");
}
}
/// <summary>
/// This static method helps encrypt the given data set
/// </summary>
/// <param name="ConfigurationPath">String : The configuration file path</param>
public static void Decrypt(string ConfigurationPath)
{
//Create a new ExeConfigurationFileMap
ExeConfigurationFileMap oFile = new ExeConfigurationFileMap();
//Precise its path
oFile.ExeConfigFilename = Application.StartupPath + @"\EncryptConfigurationFile.exe.config";
//Create a new configuration object related to the configuration file
Configuration oConfiguration = ConfigurationManager.OpenMappedExeConfiguration(oFile, ConfigurationUserLevel.None);
//Create a section and set it as the targeted section
ConnectionStringsSection oSection = oConfiguration.GetSection("connectionStrings") as ConnectionStringsSection;
if (oSection != null && oSection.SectionInformation.IsProtected)
{
oSection.SectionInformation.UnprotectSection();
oConfiguration.Save();
MessageBox.Show("Connection string decrypted");
}
}
}
}
To consume this class services lets add a form to our project then add two buttons one to encrypt and the other to decrypt as bellow:
Figure 7
Then populate the both event handlers' methods according to the two buttons as follow:
string ConfigurationFilePath = "";
private void button1_Click(object sender, EventArgs e)
{
ConfigurationFilePath = Application.StartupPath + @"\EncryptConfigurationFile.exe.config";
ConfigurationSectionEncryptor.Encrypt(ConfigurationFilePath);
}
private void button2_Click(object sender, EventArgs e)
{
ConfigurationSectionEncryptor.Decrypt(ConfigurationFilePath);
}
Now, run the application and try to encrypt the decrypt the targeted section.
The hard one:
The other method consists on using a custom protection provider; In fact, the .Net Framework provides us a base class for this case, namely the ProtectedConfigurationProvider, which is an abstract class that enables developers to design their proper configuration section protection providers. So before plug into the development let's perform our design pattern concerning this custom protection provider. First, to be more methodic let's outline our new class by defining this interface:
Figure 8
In this interface I propose the principals methods and properties that our custom provider is going to implement. I also give developers those use my proper solution the occasion to develop their custom provider according to my vision by implementing this interface. As second step, I introduce my custom provider witch I give it CustomProtectionProvider as name:
Figure 9
The CustomProtectionProvider inherits the base class ProtectedConfigurationProvider and implements the ICustomProtectionProvider interface.
Now, I try to introduce all the class members:
|
Name |
Type |
Description |
|
Private string CustomProviderName; |
Field |
Represents the name of your custom provider object, it is used to identify different objects of the same type |
|
private string _ConfigFilePath; |
Field |
Represents the configuration file path |
|
private string _SectionName; |
Field |
Represents the targeted configuration section name |
|
private byte[] _Key; |
Byte array |
Represents the key used to encrypt/decrypt data |
|
private byte[] _IV; |
Byte array |
Represents the initial vector value, also used to encrypt/decrypt data |
|
Public CustomProtectionProvider(string CustomProviderName, CryptAlgorythmToUse Algorithm[1][1][1], Generate Generate[2][2][2]) |
First constructor |
This constructor is overloaded by
|
|
public CustomProtectionProvider(string CustomProviderName, string ConfigFilePath, CryptAlgorythmToUse Algorithm, Generate Generate) |
Second constructor |
This constructor is overloaded by
|
|
public string ConfigFilePath |
Property |
This property enables user enter the configuration file path |
|
public override string Name |
Method |
This method returns the custom provider name |
|
public override string Description |
Method |
This method returns the custom provider description |
|
public byte[] Key |
Property |
This property enables user enter and retrieve the key value |
|
public byte[] IV |
Property |
This property enables user enter and retrieve the initial vector value |
|
public string SectionName |
Property |
This property enables user enter and retrieves the configuration section name |
|
public override XmlNode Encrypt(XmlNode node) |
Method |
This method encrypts the targeted configuration section |
|
public override XmlNode Decrypt(XmlNode node) |
Method |
This method decrypt the targeted configuration section |
|
public override int GetHashCode() |
Method |
This method returns a hash code of the base class |
|
private string AddTags(string input) |
Method |
This method wraps the encrypted configuration section in <EncryptedData></EncryptedData> |
I provide an enumeration to enable the class user select witch encryption/decryption algorithm to use, he/she has choice between Rijndael and TripleDES

I give the user the choice the Generate enumeration whether, he lets the object generate the key and the IV values or he enters by him self the given values but be careful, first, the same key and IV values are used in encryption and decryption, second, the both key and IV must be saved in a safe place like and isolated storage for example.

And now here is the class implementation:

Join the conversation! Your thoughts help the community grow.