Using the RSA Provider to Encrypt a Connection String in Web.config in a Web Farm
Post date: Mar 18, 2011 11:25:45 AM
To do this, you must create a custom RSA encryption key container and deploy the same key container on all servers in your Web farm. This won't work by default because the default RSA encryption key, "NetFrameworkConfigurationKey", is different for each computer.
To use RSA encryption in a Web farm
Run the following command from a command prompt to create a custom RSA encryption key:
aspnet_regiis -pc "CustomKeys" -exp
The -exp switch indicates that the keys are exportable.
If the command is successful, you will see the following output:
Creating RSA Key container...
Succeeded!
You can verify that a custom key container exists by looking for the file and checking timestamps in the following location:
\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA
\MachineKeys
Create a new Web project named WebFarmRSA. Make sure that this directory is configured as a virtual directory.
Add a Web.config configuration file to this directory.
Add a sample connectionString similar to the following example:
<connectionStrings>
<add name="MyLocalSQLServer"
connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated
Security=SSPI;" providerName="System.Data.SqlClient"/>
</connectionStrings>
Add and configure a custom protected configuration provider. To do this, add the following <configProtectedData> section to the Web.config file. Note that the key container name is set to "CustomKeys", which is the name of the key container created previously.
...
<configProtectedData>
<providers>
<add keyContainerName="CustomKeys"
useMachineContainer="true"
description="Uses RsaCryptoServiceProvider to encrypt and decrypt"
name="CustomProvider" type="System.Configuration.RsaProtec
tedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" />
</providers>
</configProtectedData>
...
Run the following command from an SDK Command Prompt to encrypt the connectionStrings section using the custom RSA key:
aspnet_regiis -pe "connectionStrings" -app "/WebFarmRSA" -prov "CustomProvider"
If the encryption is successful, you will see the following output:
Encrypting configuration section...
Succeeded!
Review the Web.config file and examine the changes. The following elements are modified:
<EncryptedData>
<CipherData>
<CipherValue>
Your modified Web.Config file, with the connectionStrings section encrypted, should be similar to the following example:
...
<connectionStrings configProtectionProvider="CustomProvider">
<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>MWOaFwkByLRrvoGYeFUPMmN7e9uwC0D7gFEeyxs3Obll710dLQvD5XaM
WcRxg1WwtOE9nysPQRrIJUaCm0b26LGUoa/giGEfvWnslU2kig9SPICzsQAqU
SB/inhRckWceb2xdy7TT+
EI/vfsu6itJwE2AicMCTwx5I828mP8lV4=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>IKO9jezdlJ/k1snyw5+e11cd9IVTlVfHBHSiYLgICf1EnMNd5WxVDW
Tuif7oP4Emgaoa+ewLnETSN411Gow28EKcLpbKWJDOC/9o7g503YM4cnIvkQO
omkYlL+MzMb3Rc1FSLiM9ncKQLZi+JkRhlDIxFlsrFpKJhdNf5A0Sq2P71
ZLI6G6QDCehHyn3kCZyBmVWJ0ueoGWXV4y</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
...
Run the following command from a .NET command prompt to export the custom RSA encryption key:
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, you will see the following output:
Exporting RSA Keys to file...
Succeeded!
Deploy the application and the encrypted Web.config file on a different server computer. Also copy the CustomKeys.xml file to a local directory on the other server, for example to the C:\ directory.
On the destination server, run the following command from a command prompt to import the custom RSA encryption keys:
aspnet_regiis -pi "CustomKeys" "C:\CustomKeys.xml"
If the command is successful, you will see the following output:
Importing RSA Keys from file..
Succeeded!
Note After you have finished exporting and importing the RSA keys, it is important for security reasons to delete the CustomsKeys.xml file from both machines.
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 are not sure which identity your application uses, you can check this by adding the following code to a Web page:
using System.Security.Principal;
...
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 grants 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.
Add the following Default.aspx Web page to your application's virtual directory, and then browse to this page to verify that encryption and decryption work 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 previously in the Web.config file.