.Net, IIS, Security, Sitecore, Web, XML

Encrypting .NET Config Files in a Shared Development Environment

This page will attempt to describe how to encrypt sensitive information contained in .NET config files using the RSA Key Container, as well as how to export/import the key from that container so that other developers may use the same key to work on the same project.

Helpful Tips: The aspnet_regiis.exe utility must be run as a administrator, otherwise you may receive “duplicate object” errors. In addition, you will want to run Visual Studio as an administrator to ensure the program has access to the RSA Key Container store.

Creating a Custom RSA Key Container

In this part we will create an RSA key container by using aspnet_regiis.exe with the -pc option. This identifies the RSA key container as a user-level key container. RSA key containers must be identified as either user-level (by using the -pku option) or machine-level (by not using the -pku option). For more information about machine-level and user-level RSA key containers, see Understanding Machine-Level and User-Level RSA Key Containers.

In this example the following command will create an RSA key container named SampleKeys that is a machine-level key container and is exportable:

cd \WINDOWS\Microsoft.Net\Framework\v4.0.*
aspnet_regiis -pc "SampleKeys"–exp

Adding your provider to the web.config

The following example shows the configProtectedData section of a Web.config file. The section specifies an RsaProtectedConfigurationProvider that uses a machine-level RSA key container named SampleKeys.

<configProtectedData>
   <providers>
    <add keyContainerName="SampleKeys" useMachineContainer="true" description="RsaCryptoServiceProvider" name="SampleKeys" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
   </providers>
</configProtectedData>

Importing and Exporting the Key Container

In order for another developer to run your project (encrypted by your key) you will need to  export a key to be used by another developer:

aspnet_regiis -px "SampleKeys" "C:\keys.xml" -pri

Once you pass this along to another user to use then import with the following command:

aspnet_regiis -pi "SampleKeys" "C:\keys.xml"

If this is a machine level container, the code should now run without the need to assign permissions. However, if it’s a user container (i.e. your app pool is ran by a specific user or service account), additional permissions may need to be assigned:

aspnet_regiis -pa "SampleKeys" "NT AUTHORITY\NETWORK SERVICE"
aspnet_regiis -pa "SampleKeys" "[impersonation account]"

To use the default RsaProtectedConfigurationProvider specified in the machine configuration, you must first grant the application’s Windows identity access to the machine key container named NetFrameworkConfigurationKey, which is the key container specified for the default provider. For example, the following command grants the NETWORK SERVICE account access to the RSA key container used by the default RsaProtectedConfigurationProvider:

aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AUTHORITY\NETWORK SERVICE"

Encrypting and Decrypting Config Sections

.NET allows specific sections of a config file to be encrypted, so non-sensitive information can still be accessed. To encrypt a section:

aspnet_regiis -pef [section] [path] -prov [provider]

Where [section] is the name of the config section, relative to the configuration tag. [path] is the relative path to the directory containing the web.config file. For example, the following commands will encrypt the appSettings section as well as the impersonation credentials:

cd C:\SolutionFolder
aspnet_regiis -pef appSettings ProjectFolder -prov SampleKeys
aspnet_regiis -pef system.web/identity ProjectFolder -prov SampleKeys

To decrypt the appSettings section:

aspnet_regiis -pdf appSettings ProjectFolder

Partially Encrypting a Section

It may be necessary to only encrypt part of a section in a web.config file. For example, if the appSettings section contains multiple, non-sensitive keys and only a subset contain sensitive information. To encrypt only a few keys, a second appSettings section must be created and the new keys moved into it. The keys are accessed exactly the same way in the code, so no coding changes are needed.

First, register a new section name called secureAppSettings by placing the following XML under the configuration node:

<configSections>
<section name="secureAppSettings" type="System.Configuration.NameValueSectionHandler, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>

Next, create a new section called secureAppSettings and move the sensitive keys under it:

<secureAppSettings>
    <add key="Username" value="XXX" />
    <add key="Password" value="XXX" />
</secureAppSettings>
<appSettings>
    <add key="NotSensitive" value="XXX" />
</appSettings>

Finally, the new secure section can be encrypted and decrypted independently of the existing appSettings section:

aspnet_regiis -pef secureAppSettings ProjectFolder -prov ProviderName

App.config

This Microsoft utility was designed for web.config files. It will not find app.config files for other project types. To encrypt these config files, just rename them to web.config prior to encrypting, then rename back afterwards.

Other Helpful Links:

.Net, IIS, Programming, Web, XML

Using Encryption and Decryption on a .Net Web.Config ConnectionString

If you have .Net web applications that are connecting to data sources that you do not want other users to know about then chances are it is about time to start encrypting the connection strings. Why is this important? If you have an external website that fails (and you do not have any custom error pages) then you may expose connection information in the stack trace or error messages. Also, you do not want to allow other developers that stumble upon your connection string to see your connection information in clear text. Over time and many applications later I went from trying to remember paths and commands and have created batch files to perform this on a minimal web.config.

I am going to walk through how to create some encrypt/decrypt batch files and how these are used in conjunction with your web.config.

  • Ensure you have a .Net Framework installed to use the aspnet_regiis.exe program. For this example we are using .Net Framework 4.0.
  • Create a folder for all of your files to sit inside of. For this demo let’s call the folder “decrypter”. Make note of where you are storing this folder to use in your batch files in the next steps. For this example let’s assume “C:\decrypter”
  • Open notepad and create a file named Decrypt.bat and add the following information (take note of the path you’ll need to update based on where you are going to store your folder):
echo Decrypting connection strings
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\decrypter"
Pause
  • Open notepad again and create a file named Encrypt.bat and add the following information (take note of the path you’ll need to update based on where you are going to store your folder):
echo Encrypting connection strings
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\decrypter"
Pause
  • Open notepad again and create a web.config file and insert your connectionstrings section inside (make sure to place this file in the same location as the batch files, you’ll use this over and over):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
 <add name="Demo" connectionString="Data Source=123.45.67.89;Initial Catalog=DemoCatalog;Persist Security Info=True;User ID=specialuser;Password=specialpassword" providerName="System.Data.SqlClient" />
 </connectionStrings>
</configuration>
  • Once you have that saved, run your Encrypt.bat as administrator. You should see the following:

en-example

  • Your connection strings are now encrypted. Review your web.config and see:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
 <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
 xmlns="http://www.w3.org/2001/04/xmlenc#">
 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
 <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
 <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
 <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
 <KeyName>Rsa Key</KeyName>
 </KeyInfo>
 <CipherData>
 <CipherValue>You'll Have A Cipher Here.</CipherValue>
 </CipherData>
 </EncryptedKey>
 </KeyInfo>
 <CipherData>
 <CipherValue>You'll Have A Cipher Here.</CipherValue>
 </CipherData>
 </EncryptedData>
</connectionStrings>
</configuration>
  • You can now take the connectionStrings section and replace your cleartext version for your application.
  • Should you ever need to update your connectionStrings simply place the encrypted version back on your minimal web.config and run the Decrypt.bat (as administrator). This is what you should see:

de-example

  • You should then see your original clear text connection string. Hope this helps.
  • Things of note:
    • You can also do this with other sections of the web.config (just rename connectionStrings to whatever section you need to encrypt)
    • If you have comments inside of your connectionString the encryption and decryption will remove them.
    • Another reference: https://msdn.microsoft.com/en-us/library/zhhddkxy.aspx
Programming, Sitecore

Encrypt And Decrypt A Sitecore ConnectionStrings.Config File

Encrypting .Net application web.config files are easy enough. However Sitecore is NOT a fan of you messing with the web.config. This is even part of the reason the connection strings are stored out into a separate file in Sitecore. I’ll go through a quick method of taking care of doing it on the separate Sitecore file.

  • Ensure you have .Net framework installed where you are going to perform the encryption (my examples are 4.0, you can use 2.0 if need be)
  • !!!IMPORTANT!!! Make a backup of your Sitecore ConnectionStrings.config file
  • Create a folder on C: to hold your encrypt/decrypt batch files (example will be C:\decrypter) where the .Net framework exists
  • Open notepad and create a batch file (encrypt.bat), put the following in for your encryption statement and then save it to your folder you just created
echo Encrypting app_config/connectionstrings.config
 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pef "connectionStrings" "C:\decrypter"
 Pause
  • Repeat this step for the decryption statement (decrypt.bat)
echo Encrypting app_config/connectionstrings.config
 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -pdf "connectionStrings" "C:\decrypter"
 Pause
  • Create a blank web.config (THIS IS YOUR WEB.CONFIG YOU MADE AND NOT THE SITECORE WEB.CONFIG!!!), put and wrap your Sitecore connection strings (from ConnectionStrings.config) inside and save it to the folder you created. it should look something like:
<?xml version="1.0" encoding="utf-8"?>
 <configuration>
 <connectionStrings>
 <add name="core" connectionString="user id=sitecoreuser;password=sitecorepw;Data Source=servernameorip;Database=Sitecore_Core" />
 <add name="master" connectionString="user id=sitecoreuser;password=sitecorepw;Data Source=servernameorip;Database=Sitecore_Master" />
 <add name="web" connectionString="user id=sitecoresql;password=sitecorepw;Data Source=servernameorip;Database=Sitecore_Web" />
 <add name="reporting" connectionString="user id=sitecoresql;password=sitecorepw;Data Source=servernameorip;Database=Sitecore_Analytics" />
 </connectionStrings>
 </configuration>
  •  Once you have both batch files and the web.config then run the encrypt batch file as an administrator. It will look something like this:

encrypt

  • You’ll then have a web.config in your folder now similar to this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">
<EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<KeyName>Rsa Key</KeyName>
</KeyInfo>
<CipherData>
<CipherValue>(you'll have a long cipher here)</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>(you'll have a long cipher here)</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
</configuration>
  • Once completed take the connectionStrings section of the web.config and replace your ConnectionStrings.config file with the encrypted connectionStrings section (run notepad in admin mode if your sitecore is in the web root).
  • Recycle the app pool to refresh. You should now be encrypted!
  • If this fails for you at some point then replace your Sitecore connectionStrings.config file with the backup you took at the start.
  • And yes, to decrypt (to update your strings) put your encrypted connectionstrings section in your web.config (THIS IS YOUR WEB.CONFIG YOU MADE AND NOT THE SITECORE WEB.CONFIG!!!) in the windows folder you made and run the decrypt.bat as an admin. You should get:

decrypt

Again, I hope this helps someone. Questions and comments are always welcome! And for the sake of hoping I catch the skimmers here, DO NOT MODIFY THE SITECORE WEB.CONFIG. DO THIS ON THE CONNECTIONSTRINGS.CONFIG! You have been warned…