howtoencryptconfigurationsectionsusingrsainaspnet20

Cancel Edit [WikiEntry.PreviewButtonText] Save
Return to ASPNETWhidbeySecurityHowTos


How To: Encrypt Configuration Sections in ASP.NET 2.0 Using RSA

Applies To

* ASP.NET 2.0
* Windows 2003

Summary

This How To explains you how to use the RSA Protected Configuration provider and the Aspnet_regiis.exe tool to encrypt sections of your configuration files. You can use this tool to encrypt sensitive data, such as connection strings, held in Web.config and Machine.config. RSA is well suited to encrypting configuration files used on multiple servers in a Web farm due to the fact that you can easily export and import RSA key containers.

Contents

* Overview
* What’s New in 2.0?
* Identifying the configuration sections to be encrypted.
* Identifying the protection configuration provider to be used.
* Using the RSA Provider with machine store to encrypt a connection string in Web.config
* Using the RSA Provider with user store to encrypt a connection string in Web.config
* Web Farm Scenarios
* Additional Resources

Overview

Configuration files such as Web.config are often used to hold sensitive information such as user names, passwords, database connection strings and encryption keys. The most common sections that contain sensitive information that you need to encrypt are:
* <appSettings> Custom application settings.
* <connectionStrings> Connection strings.
* <identity> Web application identity. Can contain impersonation credentials.
* <sessionState> Contains connection string for out of process session provider.

Encrypting and decrypting data has a performance overhead. To keep this overhead to a minimum, only encrypt the specific sections of your configuration file that store sensitive data.

What’s New in 2.0?

Prior to .NET Framework 2.0, there was limited support for configuration file encryption. The .NET Framework 2.0 introduces a Protected Configuration feature which you can use to encrypt sensitive configuration file data by using a command line tool. The following two Protected Configuration providers are provided although you can also implement custom providers.
* RSAProtectedConfigurationProvider This is the default provider and uses the RSA public key encryption to encrypt and decrypt data.
* DPAPIProtectedConfigurationProvider This provider uses the Windows Data Protection API (DPAPI) to encrypt and decrypt data.

This How To explains how to use the Aspnet_Regiis.exe tool with the RSAProtectedConfigurationProvider to encrypt sections of your configuration file. This provider uses RSA public key encryption. Note that ASP.NET automatically decrypts configuration sections when processing them, and so you do not need to write any additional decryption code.

Summary of Steps

To encrypt configuration sections by using the RSA Data Protection provider, perform the following steps:
* Step 1: Identify the configuration sections to be encrypted
* Step 2: Choose machine or user level key containers
* Step 3: Encrypt your configuration file data

Step 1: Identify the Configuration Sections to Be Encrypted

Encrypting and decrypting data has a performance overhead. To keep this overhead to a minimum, only encrypt the specific sections of your configuration file that store sensitive data.
Sections You Cannot Encrypt Using Protected Configuration
If you store sensitive data in any of the following configuration sections, you cannot encrypt it by using Protected Configuration and the Aspnet_regiis.exe tool.

<processModel>, <runtime>, <mscorlib>, <startup>, <system.runtime.remoting>, <protectedData>, <satelliteassemblies>, <cryptographySettings>, <cryptoNameMapping>, and <cryptoClasses>.

For the configuration sections listed above, you should use the Aspnet_setreg.exe tool, which is also available for earlier versions of the .NET Framework.
For more information about using the Aspnet_setreg tool to encrypt data in these configuration sections, see Microsoft Knowledge Base article 329290, "How to use the ASP.NET utility to encrypt credentials and session state connection strings" at http://support.microsoft.com/default.aspx?scid=kb;en-us;329290.

Step 2: Choose Machine or User-Level Key Containers

The RSAProtectedConfigurationProvider supports machine and user level key containers for key storage. Windows makes machine-level key containers available to all users while a user-level key container is available to that user only.
The choice of container is largely dependent on whether or not your application shares a server with other applications and whether or not sensitive data must be kept private to each application.

Machine Key Container

Use a machine-level key container in the following situations:
* Your application runs on its own dedicated server with no other applications.
* You have multiple applications on the same server and you want those applications to be able to share sensitive information and the same encryption key.

RSA machine key containers are stored in the following folder.
		 \Documents and Settings\All Users\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

User Key Container

Use a user-level key container if you run your application in a shared hosting environment and you want to ensure that your application's sensitive data is not accessible to other applications on the server. In this scenario, each application should have a separate identity and the resources for the application such as files, and databases should be restricted to that identity.
RSA user-level key containers are stored in the following folder.

		 \Documents and Settings\{UserName}\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

Step 3: Encrypt Your Configuration File Data

This step shows you how to encrypt a connection string in Web.config. It shows you how to do this by using the machine store and then by using the user store.
Using RSA with a Machine-Level Key Container to Encrypt a Connection String in Web.Config
The RSAProtectedConfigurationProvider is the default provider and is configured to use the machine-level key container.

To encrypt the connectionStrings section in Web.config:

1. Create a new Web site named MachineRSA. Make sure this directory is configured as a virtual directory.
2. Add a Web.config configuration file to this directory.
3. Add a sample connectionString like the one shown below.


		 <connectionStrings>
		  <add name="MyLocalSQLServer" 
		       connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
		 </connectionStrings>
	

4. Encrypt the connectionStrings section by running the following command from a command window.

		 aspnet_regiis -pe "connectionStrings" -app "/MachineRSA" 
	

* The -pe switch specifies the configuration section to encrypt. This is the XML element name of the configuration section.
* Note – For nested elements like the <pages> section which is inside <system.web>, the XML name must include any containing section groups, for example “system.web/pages".
* The -app switch specifies your Web application's virtual path. If it’s a nested application, you need to specify the nested path from the root directory, for example “/test/aspnet/MachineRSA”
* Note that while using the default provider with default settings, you do not need to use the –prov option.

If the command is successful, you will see the following output:

Encrypting configuration section...
Succeeded!

Note that RSA machine key containers are stored in the following folder.

		 \Documents and Settings\All Users\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

5. Review Web.config and examine the changes. The following elements are created.

		 <protectedData>
		 [<EncryptedData>]
		 [<CipherData>]
	

Your modified Web.Config file, with the connectionStrings section encrypted should look similar to the following.

		 ...
		 <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] Recipient="" 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>cbJNxB4OmxwzGVVn2R7b1+YsRtlik95RhsTnA6zMjkW/ApBl4q/3+HrE3NRykcoyVgFsGKO2aRLkyQvnzEt2nwptwGsonDNOhbrNLa4wGDXXq5YNnEUQmhAdPlaQQt8HAQ0/hhQOgjUib6SnlWLzlH5ZlpBGiuy4zr6EahbBztA=</CipherValue>
		     [</CipherData>]
		    [</EncryptedKey>]
		   [</KeyInfo>]
		   [<CipherData>]
		     <CipherValue>WkEoLFnva9rjH4faZu50eyJHV3a7+7mj3JnO9mUMaaZX78dv1N/Q3TJ092ZGZ9HKJtomU6dhL9K5P6LHMvbrILDsB/4vdoaHeepAoKkHc5d3Nva27mltxvq+IT0KaAtj3O6EGsrllUWX4rBeq18w6eyQqZqW3eHM1HJq6PlcA9K2y3HenrY06BoKzosOHo9OPUpHK2kNoOxXg1XvP0AuBFAj7UUjXT4QeoGIi15T3JT/YerHJ/mhZw15dHBfbTN36d60yBdHRTBKrvQQ78H9zzT15lfmJTrX</CipherValue>
		   [</CipherData>]
		  [</EncryptedData>]
		 </connectionStrings>
		 ...
	

6. Add the following Default.aspx Web page to your application's virtual directory and then browse to this page to verify the encryption and decryption works correctly.

		 <%@ Page Language="C#" %>
	

		 <script runat="server">
		    protected void Page_Load(object sender, [EventArgs] e)
		    {
		        Response.Write("Clear text connection string is: " + 
		                 [ConfigurationManager.ConnectionStrings]
		                            ["MyLocalSQLServer"].ConnectionString);
		    }
		 </script>
		 <html>
		  <body/>
		 </html>
	

MyLocalSQLServer is the name of the connection string you specified in Web.config earlier.
If your ASP.NET application identity does not have access to the .NET Framework Configuration Key store, the following message is returned.

Parser Error Message: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: Keyset does not exist

* To grant access to the ASP.NET application identity:
If you are not sure which identity, you can check the identity, from a Web page by using the following code.

		 protected void Page_Load(object sender, [EventArgs] e)
		 {
		        [Response.Write(WindowsIdentity.GetCurrent().Name);]
		 }
	

By default, ASP.NET applications on Windows Server 2003 run using the NT Authority\Network Service account. The following command shows you how to grant this account access to the NetFrameworkConfigurationKey store:

		 aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT Authority\Network Service"
	

If the command runs successfully you will see the following output.

Adding ACL for access to the RSA Key container...
Succeeded!

You can check the ACL of the file in the following folder:

		 \Documents and Settings\All Users\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

Your RSA key container file will be the one in this folder with the most recent timestamp.

7. To revert the connectionStrings section to clear text, run the following command from the command prompt:

		 aspnet_regiis -pd "connectionStrings" -app "/MachineRSA"
	

If successful, the following output is produced.
Decrypting configuration section…
Succeeded!

Using RSA with a User-level Key Container to Encrypt a Connection String in Web.config

The following steps show you how to encrypt a <connectionStrings> section, by using the RSAProtectedConfigurationProvider (RSA) with a user-level key container.

To encrypt the connectionStrings section in Web.config:

1. Create a new Web site named UserRSA. Make sure this directory is configured as a virtual directory.
2. Add a Web.config configuration file to this directory.
3. Add a sample connectionString like the one shown below.


		 <connectionStrings>
		  <add name="MyLocalSQLServer" 
		       connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;"  providerName="System.Data.SqlClient"/>
		 </connectionStrings>
	

4. Add and configure a protected configuration provider to use a user-level key container. To do so, add the following <configProtectedData> section to your Web.config. Note that you must set useMachineContainer=“false” to instruct the provider to use the user-level key container. You must also use a unique provider name or a runtime error will be generated.

		 [<configProtectedData>]
		  <providers>   
		    <add keyContainerName="NetFrameworkConfigurationKey"
		      useMachineContainer="false"
		      description="Uses [RsaCryptoServiceProvider] to encrypt and decrypt"
		      name="MyUserRSAProtectedConfigurationprovider" 
		 type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0,  Culture=neutral,  PublicKeyToken=b03f5f7f11d50a3a" />
		    </providers>   
		 [</configProtectedData>]
	

5. Encrypt the connectionStrings section by running the following command from a command window.

		 aspnet_regiis -pe "connectionStrings" -app "/UserRSA" –prov "MyUserRSAProtectedConfigurationProvider" 
	

* The -pe switch specifies the configuration section to encrypt. This is the XML element name of the configuration section.
* Note – For nested elements like the <pages> section which is inside <system.web>, the XML name must include any containing section groups, for example “system.web/pages".
* The -app switch specifies your Web application's virtual path. If it’s a nested application, you need to specify the nested path from the root directory, for example “/test/aspnet/MachineRSA”
* The –prov switch specifies the provider name. In this case, this is set to “MyUserRSAProtectedConfigurationProvider” which is the name you specified when configuring the provider in the previous step.

If the command is successful, you will see the following output:

Encrypting configuration section...
Succeeded!

RSA user-level key containers are stored in the following folder.

		 \Documents and Settings\{UserName}\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

6. Review Web.config and examine the changes. The following elements are created.

		 [<configProtectedData>]
		 [<EncryptedData>]
		 [<CipherData>]
	

Your modified Web.Config file, with the connectionStrings section encrypted should look similar to the following.

		 ...
		 <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] Recipient="" 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>lI9oI8gSB3njlweLsDeWwydDVGZ5Qda5X63Bj3TXGW7A/WrYZ/WFo9mzHEvVw80M5uK7izia58SEIZ34Fgbrj7gDHrFJsbCk2in2/PaJeSbT9rKAJc04I/+v1hmtM4RHn8rQh6nr47iXyFlH5U0BrXo9W0EjQ2Yx0q6NR6xXVkA=</CipherValue>
		     [</CipherData>]
		    [</EncryptedKey>]
		   [</KeyInfo>]
		   [<CipherData>]
		     <CipherValue>M0VMQFQyUXKJnaHifQM+nkejn4zGEVQAzn60292VrVsrI0bvl5ZZJBJdXPHAuyObzTBm02A25Z+/fAW4ROdP24zCJa1/sfEC50XdKgKDcIMRmzTlkfd2OaeAAgSGWk64xaVXcnwhx/LUkBKvMHcvllb7oajrynfbUs0FjDxidEH82n4L8lQOCgY547CBcovpHJXAYrXGnWcobVMzsYRv1Q6tF1ZnuQzGrpUsg0uqFvVGLSGqNJZv2F9z1KDZdRUIXTapXh+bJOyAQZuSmRbpugD3KE+Dxm7n</CipherValue>
		   [</CipherData>]
		  [</EncryptedData>]
		 </connectionStrings>
		 ...
	

7. Add the following Default.aspx Web page to your application's virtual directory and then browse to this page to verify the encryption and decryption works correctly.

		 <%@ Page Language="C#" %>
	

		 <script runat="server">
		    protected void Page_Load(object sender, [EventArgs] e)
		    {
		        Response.Write("Clear text connection string is: " + 
		                 [ConfigurationManager.ConnectionStrings]
		                            ["MyLocalSQLServer"].ConnectionString);
		    }
		 </script>
		 <html>
		  <body/>
		 </html>
	

MyLocalSQLServer is the name of the connection string you specified in Web.config earlier.
By default the ASP.NET applications run under the NT AUTHORITY \ Network Service account. When you access encrypted configuration sections using RSA encryption with the user-level key container, make sure that your application is running with the same user identity as the account you used to encrypt the data.
For example, by running the Aspnet_regiis command from the command line to encrypt data, the interactive account you used to logon to Windows is used to perform the encryption and the RSA key container is stored in that user's user profile. To ensure that the same account is used at runtime, you will need to configure your Web application in IIS to use Integrated Windows authentication and in Web.config you will need to enable impersonation as follows:

		 <system.web>
		  . . .
		  <identity impersonate="true" />
		  . . .
		 </system.web>
	

If your application runs under a different account than the one used to encrypt the data, ASP.NET will be unable to access the RSA user-level key container and the following error will be generated:

Parser Error Message: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: Keyset does not exist

8. To revert the connectionStrings section to clear text, run the following command from the command prompt:

		 aspnet_regiis -pd "connectionStrings" -app "/UserRSA"
	

If successful, the following output is produced.

Decrypting configuration section…
Succeeded

Web Farm Scenarios

You can use RSA encryption in Web farms, because you can export RSA keys. You need to do this if you encrypt data in a Web.config file prior to deploying it to other servers in a Web farm. In this case, the private key required to decrypt the data must be exported and deployed to the other servers.

Using the RSA Provider to Encrypt a Connection String in Web.config in a Web Farm

To do this, you must create a custom RSA encryption key container and deploy the same key container on all the servers in your Web farm. This won't work by default because the default RSA encryption key "NetFrameworkConfigurationKey" will be different for each machine.

To use RSA encryption in a Web farm:

1. Create a custom RSA encryption key by running the following command.

		 aspnet_regiis -pc "CustomKeys" -exp
	

The -exp switch indicates that the keys are exportable.
If the command is successful the following output is produced.

Creating RSA Key container...
Succeeded!

You can verify that a custom key container by looking for the file (checking timestamps) in the following location:

		 \Documents and Settings\All Users\Application [Data\Microsoft\Crypto\RSA\MachineKeys] By checking the time/stamp
	

2. Create a new Web project named WebFarmRSA. Make sure this directory is configured as a virtual directory.
3. Add a Web.config configuration file to this directory.
4. Add a sample connectionString like the one shown below.

		 <connectionStrings>
		  <add name="MyLocalSQLServer" 
		       connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;"  providerName="System.Data.SqlClient"/>
		 </connectionStrings>
	

5. Add and configure a custom protected configuration provider. To do so, add the following <configProtectedData> section to your Web.config. Note that the key container name is set to "CustomKeys" which is the name of the key container created earlier.

		 ...
		 [<configProtectedData>]
		  <providers>
	
<add keyContainerName="CustomKeys"
useMachineContainer="true"
description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
name="CustomProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
		  </providers>
		 [</configProtectedData>]
		 ...
	

6. Encrypt the connectionStrings section using the custom RSA key by running the following command from a command window.

		 aspnet_regiis -pe "connectionStrings" -app "/WebFarmRSA " -prov "CustomProvider"
	

If the encryption is successful, the following output is produced.

Encrypting configuration section...
Succeeded!

7. Review Web.config and examine the changes. The following elements are modified.

		 [<configProtectedData>]
		 [<EncryptedData>]
		 [<CipherData>]
	

Your modified Web.Config file, with the connectionStrings section encrypted should look similar to the following.

		 ...
		 <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] Recipient="" 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>Lx8o8103pNtEM/gsQ8Dyi3oybV75rJHAGJyTINwTj7K+d8O4ZpYh8qq6Q0uLrgvjGqAHv2JDFw3HtUQa+S3C7D7qKg/HkboyICem2HHGWBrSz/Mx95BlYGuXexN3C4kUWF1RSFANNIMTiXTqzM7mlzJcjCFf/eU2NGxjSmcWKMY=</CipherValue>
		     [</CipherData>]
		    [</EncryptedKey>]
		   [</KeyInfo>]
		   [<CipherData>]
		     <CipherValue>cr6520esvHKwnZbk51eLgKwA/GE93ZoKqoBmotdj/H8t+rLkXHQJP9dvVc/nfVg4RVBW34qsggC51HzMEvSy6T4GZCppBYmMB58iOJd7GhvUIfBz5oQaAzmwNIkktZd3XAfYHui8WI/3oJ4ZzakD9CWh+jnw2wK1lWQZU9jF064LDE9irYGg65VINGyoqsK6wQeOzNPt1nxqP+zXiE3/rNzmHs2sBTlagLnp9OWLJGRkMWOJkDmbEJltkwVewtm2Csb3i5Yz4mtXLgnezK0fZjs7NCspqX6x</CipherValue>
		   [</CipherData>]
		  [</EncryptedData>]
		 </connectionStrings>
		 ...
	

8. Export the custom RSA encryption key by running the following command.

		 aspnet_regiis -px "CustomKeys" "C:\CustomKeys.xml" -pri
	

The -pri switch causes the private and public key to be exported. This enables both encryption and decryption. Without the –pri switch, you would only be able to encrypt data with the exported key.
If the command is successful the following output is produced.
Exporting RSA Keys to file...
Succeeded!

9. Deploy the application and the encrypted Web.config file to a different machine. Also copy the CustomKeys.xml file to a local directory on the other machine.
10. Import the custom RSA encryption keys on the destination server by running the following command.

		 aspnet_regiis -pi "CustomKeys" "C:\CustomKeys.xml"
	

If the command is successful the following output is produced.
Importing RSA Keys from file..
Succeeded!

11. Grant access to the ASP.NET application identity.
The account used to run your Web application must be able to read the RSA key container. If you’re not sure which identity your application uses, you can check this by adding the following code to a Web page.
		 protected void Page_Load(object sender, [EventArgs] e)
		 {
		        [Response.Write(WindowsIdentity.GetCurrent().Name);]
		 }
	

By default, ASP.NET applications on Windows Server 2003 run using the NT Authority\Network Service account. The following command shows you how to grant this account access to the CustomKeys store:

		 aspnet_regiis -pa "CustomKeys" "NT Authority\Network Service"
	

If the command runs successfully you will see the following output.

Adding ACL for access to the RSA Key container...
Succeeded!

You can check the ACL of the file in the following folder:
		 \Documents and Settings\All Users\Application [Data\Microsoft\Crypto\RSA\MachineKeys]
	

Your RSA key container file will be the one in this folder with the most recent timestamp.

2. Add the following Default.aspx Web page to your application's virtual directory and then browse to this page to verify the encryption and decryption works correctly.

		 <%@ Page Language="C#" %>
	

		 <script runat="server">
		    protected void Page_Load(object sender, [EventArgs] e)
		    {
		        Response.Write("Clear text connection string is: " + 
		                 [ConfigurationManager.ConnectionStrings]
		                            ["MyLocalSQLServer"].ConnectionString);
		    }
		 </script>
		 <html>
		  <body/>
		 </html>
	

MyLocalSQLServer is the name of the connection string you specified in Web.config earlier.

Additional Resources

* "How To: Encrypt Configuration Sections in ASP.NET 2.0 Using DPAPI."




Return to ASPNETWhidbeySecurityHowTos
Microsoft Communities