Wednesday, April 16, 2008

Encrypting .NET configuration files through code

Encryption support for configuration files was added to the .NET Framework beginning with version 2.0. The .NET Framework libraries include full support for controlling encryption and decryption in code. I include examples in both VB.NET and C# to demonstrate the encrypting and decryption of configuration file sections.

Protect sensitive data

Encrypting configuration data improves application security by making it difficult for users to view the data even if they access the configuration file. There are two protected configuration providers included with ASP.NET: RSAProtectedConfigurationProvider and DPAPIProtectedConfigurationProvider. RSAProtectedConfigurationProvider uses the RSACryptoServiceProvider to encrypt configuration sections using RSA public key encryption to encrypt and decrypt data. DPAPIProtectedConfigurationProvider uses the Windows Data Protection API (DPAPI) to encrypt configuration sections using the built-in cryptography capabilities of Windows. You can also create your own protected settings providers if needed. While a user will have a hard time dealing with encrypted data, ASP.NET has no problems. You can use both of these providers in ASP.NET code.

Using code

The .NET Framework 2.0 allows you to encrypt most configuration sections within the Web.config or machine.config files. The System.Web.Configuration namespace is used to encrypt configuration files via code. It contains two methods associated with encryption: ProtectSection and UnprotectSection.

|> ProtectSection: Marks a configuration section for protection. The name of the provider to be used for the encryption is passed to the method as its only parameter (a string value). |> UnprotectSection: Removes the protected configuration encryption from the associated configuration section. It has no parameters.

As an example, the following simple ASP.NET web.config file demonstrates encryption and decryption of configuration data:

The following VB.NET code from an ASP.NET Web form encrypts the connectionStrings section of the file:

Public Sub Page_Load() Dim config As Configuration Dim configSection As ConfigurationSection config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath) If Not (config Is Nothing) Then configSection = config.GetSection("connectionStrings") If Not (configSection Is Nothing) Then If Not (configSection.SectionInformation.IsLocked) Then configSection.SectionInformation.ProtectSection ("DataProtectionConfigurationProvider") config.Save() End If End If End If End Sub

The code performs the following steps:

|> It uses the System.Web.Configuration namespace to work with the necessary classes. |> It accesses the application's web.config file via the OpenWebConfiguration method of the WebConfigurationManager class. |> It accesses the connectionStrings section of the web.config file via the GetSection method. |> The section is encrypted using the default Windows encryption scheme if the file is not locked. |> The changes to the file are saved.

The equivalent C# code follows.

protected void Page_Load(object sender, EventArgs e) { Configuration config; ConfigurationSection configSection; config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath); configSection = config.GetSection("connectionStrings"); if (configSection != null) { if (!(configSection.SectionInformation.IsLocked)) { configSection.SectionInformation.ProtectSection(" DataProtectionConfigurationProvider"); config.Save(); } } }

Once the code runs, the connectionStrings section of my web.config now appears like the following:

AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAaZ2eussTfEmhwe+kgLsWVwQAAAACAAA AAAADZgAAqAAAABAAAADnyhn4dHzOLGFsIj8QUrXgAAAAAASAAACgAAAAEAAAAKFRR3MAelpxxV6J+KEhfq nQAAAAFJOBaI5ciKhw3Ywra+G0hkZb67k0YTJmXYe5+5cpZ3Wd3H2696mEhAGQiTecOVGixqtF9lHa+Qipm MSHcVECiWYjOh/6CIQL6GED37erb4TLZSNo4U7FrE2JscNCnKaKZUtvnxVqRmjcDWU7Gm2rYRAHoDSEy0UE 7ebbcqr7LQ+Y+C7WrFk+VKf6NmN4js4vl7TJXl/Nr36Z65bvZDCxcle66rZ2yebtXMTP2bX95NasbQx0trv njJrdIdMMrLOqLDPhQLwZ4ObCxkh+Rlg4NxQAAABU+1akHFhrg+4d0AmCGE8Egt3HrA==

The following VB.NET code decrypts the section and displays its value:

Public Sub Page_Load() Dim config As Configuration Dim configSection As ConfigurationSection config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath) configSection = config.GetSection("connectionStrings") If Not (configSection Is Nothing) Then If Not (configSection.SectionInformation.IsLocked) Then configSection.SectionInformation.UnprotectSection() config.Save() End If End If End Sub

The code follows the same flow as the encrypt example with the lone exception of being the call to the UnprotectSection method to decrypt the specific section. The equivalent C# code follows:

protected void Page_Load(object sender, EventArgs e) { Configuration config; ConfigurationSection configSection; config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath); configSection = config.GetSection("connectionStrings"); if (configSection != null) { if (!(configSection.SectionInformation.IsLocked)) { configSection.SectionInformation.UnprotectSection();config.Save(); } } }

Encrypting non-Web applications

The .NET Framework supports also this type of encryption with configuration files for non-ASP.NET applications. For instance, the System.Configuration namespace includes encryption support. It follows the same approach as the previous ASP.NET examples except the Configuration class from the System.Configuration namespace is used to gain access to the configuration file. The following VB.NET code demonstrates working with an application's app.config file:

Dim config As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) Dim configSection ConfigurationSection configSection = config.ConnectionStrings If Not (configSection Is Nothing) Then If Not (configSection.ElementInformation.IsLocked) Then configSection.SectionInformation.ProtectSection ("DataProtectionConfigurationProvider") configSection.SectionInformation.ForceSave = True config.Save(ConfigurationSaveMode.Full) End If End If

The section is easily decrypted with the following VB.NET code:

Dim config As System.Configuration.Configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None) Dim configSection ConfigurationSection configSection = config.ConnectionStrings If Not (configSection Is Nothing) Then If Not (configSection.ElementInformation.IsLocked) Then configSection.SectionInformation.UnprotectSection() configSection.SectionInformation.ForceSave = True config.Save(ConfigurationSaveMode.Full) End If End If

Performance

As with everything that adds security, encrypting and decrypting configuration file sections adversely affects performance. You should test an application both with and without encryption to determine the effects for certain applications. With that said, you should only encrypt what is necessary, such as only those configuration sections that contain sensitive information like connection string and user information.

Don't make it easy

Encryption provides another roadblock for malicious users looking to gain access to sensitive information. The .NET Framework allows you to easily encrypt and decrypt configuration files using built-in or custom encryption schemes.

What kind of data do you store in configuration files? Have you used other encryption schemes in the past to hide the information? Share your experience and thoughts with the .NET community.

No comments: