Click here to Skip to main content
15,890,947 members
Articles / Security / Encryption
Tip/Trick

Create RSA Key Container and Encrypt/Decrypt Config in C#

Rate me:
Please Sign up or sign in to vote.
4.86/5 (3 votes)
19 Mar 2015CPOL3 min read 41K   4   2
This tip contains securing Web or App config sections in C# with code snippets.

Introduction

Securing connection strings and other sensitive data in .NET application can be achieved by aspnet_regiis.exe located at %systemroot%\Microsoft.NET\Framework\ in your local system (You can read more at https://msdn.microsoft.com/en-us/library/ms178372%28v=vs.140%29.aspx). The encrypted connection string or any other encrypted section can be easily read by .NET application same as non-encrypted sections. This is really nice if you want to secure any section in your App or Web Config.

Usually, there is more than one QA, UAT and Prod servers in companies and the same application is replicated in all servers with the same config file to achieve load balancing. In order to secure and read encrypted sections on each QA or Prod servers, it is good idea to create RSA Key Container. So you can create RSA Key Container on one server and export it as XML. On other servers, you only need to import that XML key and encrypted config sections would start working on that server. So the server that will have XML key would only be able to decrypt encrypted sections which is a more secure approach. You can also specify the key size when creating a new RSA Key Container, 4096 is the recommended size. Default RsaProtectedConfigurationProvider provider is 1024 in size. To read more about RSA Key Container, please see https://msdn.microsoft.com/en-us/library/yxw286t2%28v=vs.140%29.aspx.

You can create RSA Key Container, Encrypt/Decrypt using aspnet_regiis.exe commands but in this post, I will explain how to do it in C# Windows Application.

Create RSA Key Container

In order to create RSA Key Container, there might be three input parameters; Key_Name, Key_Size and Export_Key_Path.

Following is the code snippet to create a new RSA Key Container, for simplicity purposes, export XML key name is the same as Key Container Name:

C#
var cp = new CspParameters
                {
                    KeyContainerName = Key_Name,
                    Flags = CspProviderFlags.NoPrompt | CspProviderFlags.UseArchivableKey
                   | CspProviderFlags.UseMachineKeyStore,
                    KeyNumber = 1
                };
                using (var rsa = new RSACryptoServiceProvider(Key_Size, cp))
                {
                    using (
                        var fs = new FileStream(
                            String.Concat(Export_Key_Path, "\\", Key_Name, ".xml"), FileMode.Create))
                    {
                        using (StreamWriter sw = new StreamWriter(fs))
                        {
                            rsa.PersistKeyInCsp = true;
                            sw.WriteLine(rsa.ToXmlString(true));
                        }
                    }
                }

Encrypt/Decrypt AppSettings Section

For this example, I am encrypting AppSettings section of Web or App Config, but you can encrypt any section like Connection String. Input parameters for this function are Config_File_Path, Section_Name, PROVIDER_NAME and IS_Encrypt flag. The provider name can be any meaningful string.

The following code snippet will encrypt AppSetting section, if it is already encrypted, it will decrypt the specified section:

C#
var configMap = new ExeConfigurationFileMap { ExeConfigFilename = Config_File_Path};
var configuration = ConfigurationManager.OpenMappedExeConfiguration
				(configMap, ConfigurationUserLevel.None);

var configSection = configuration.GetSection(Section_Name) as AppSettingsSection;

if (configSection != null && ((!(configSection.ElementInformation.IsLocked)) 
	&& (!(configSection.SectionInformation.IsLocked))))
{
 if (!configSection.SectionInformation.IsProtected && IS_Encrypt)
 {
  CreateProtectedDataConfig(configuration);
  configSection.SectionInformation.ProtectSection(PROVIDER_NAME);
}
else
{
 configSection.SectionInformation.UnprotectSection();
}
 configSection.SectionInformation.ForceSave = true;
 configuration.Save();
}

Embed Encrypted AppSettings in Web or App Config

Once you are done with the second step Encrypt/Decrypt AppSettings Section, you can see two sections in encrypted config:

  1. configProtectedData: This section will have custom Provider Name given in the second step.
  2. appSettings: Custom Provider Name with encrypted data.

Go to your application config file where this encrypted appSettings are needed to place, remove the existing appSettings section and paste above given two sections (configProtectedData and encrypted appSettings).

So these steps are enough for a single server, you don't need to make any coding changing in .NET application, ConfigurationManager.AppSetting will still read your encrypted appSetting.

Import Existing Key Container

If you want to use the same encrypted appSettings on other servers, all you need is exported RSA Key Container XML file generated in the first step. XML file name is kept as RSA Key Container name.

Following is the code snippet to import XML Key Container, input parameter is Key_Container_Name and Import_File_Path.

C#
var prm = new CspParameters
{
  KeyContainerName = Key_Container_Name,
  Flags = CspProviderFlags.UseMachineKeyStore
};

using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(prm))
{
  using (FileStream fs = new FileStream(Import_File_Path, FileMode.Open))
  {
   using (StreamReader sr = new StreamReader(fs))
    {
     rsa.FromXmlString(sr.ReadToEnd());
     txtImportKeyContainer.Text = rsa.CspKeyContainerInfo.KeyContainerName;
    }
  }
}

Check Existing RSA Key Container

Before creating any RSA Key Container, you can check if your given RSA Key Container name does exist already, following is the code snippet, input parameter is Key_Container_Name:

C#
var cspParams = new CspParameters
{
Flags = CspProviderFlags.UseExistingKey,
KeyContainerName = Key_Container_Name 
};

try
{
  new RSACryptoServiceProvider(cspParams);
}
catch (Exception)
{
  return false;
}
return true;

Delete RSA Key Container

The following code snippet helps to delete existing RSA Key Container, input parameter is Key_Container_Name:

C#
var cp = new CspParameters { KeyContainerName = Key_Container_Name };

// Create a new instance of RSACryptoServiceProvider that accesses
// the key container.
var rsa = new RSACryptoServiceProvider(cp) { PersistKeyInCsp = false };

// Delete the key entry in the container.

// Call Clear to release resources and delete the key from the container.
rsa.Clear();

History

  • Created on 03/18/2015

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect
United States United States
A Solutions Architect with more than fourteen years of experience in application development. I mostly work in .NET, Angular, MEAN stack technologies and love to share what I do and learn during my day to day job. Please check my tutorials and blog:
https://fullstackhub.io
https://fullstackhubblog.com

Comments and Discussions

 
QuestionIncomplete Example Pin
Sean O'Brien6-Jan-17 8:45
Sean O'Brien6-Jan-17 8:45 
QuestionRSA KEY Pin
Member 128275371-Nov-16 11:48
Member 128275371-Nov-16 11:48 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.