Encrypting web.config
It’s usually a good practice to encrypt database connection strings and other sensitive configuration entries for a web application. .NET 2.0+ gives you a built-in mechanism to do this.
The instructions out there on MSDN are nice, but there doesn’t seem to be a page that outlines all the things you actually have to do to use a custom key container. I’m also faced with a deployment scenario on ancient Windows 2000 servers, and the commands are slightly different here. It’s pretty straight forward, so for posterity I’ll outline the steps here.
The core tool is delivered with the .NET framework and called aspnet_regiis.exe.
Key Generation
First of all, let’s create a new custom container to hold the application keys. Another option would be to use the system default container NetFrameworkConfigurationKey, but let’s create a container specific our application:
C:\app> aspnet_regiis -pc MyCustomContainer
Creating RSA Key container...
Succeeded!
This now created the container and a new key inside it. The next step is to export the key into an XML file:
C:\app> aspnet_regiis -px MyCustomContainer mykeys.xml
Exporting RSA Keys to file...
Succeeded!
The file mykeys.xml now contains the keys. Keep this file safe, we will need to distribute it on the web farm later. The contents of the file looks like this:
<RSAKeyValue><Modulus>5C31Pc/ppGZjWuoUdQ9HjiAIxp8UaVYvgYXz3K4i3qzpW9al6s+2kG8ktHpSfZ/y6H4qDpaqI2TU5ltYdxr4Iv6sPhnTEKMv1N7AWq/FNwVTCM8XiWXqs6K+UW7mDfCI
ArF1Fqo+kFV1LJtuPUahy2TOmnji+ZUzzuwFqzqFop0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>
Encrypt your application configuration
First of all, a new encryption provider needs to be registered in the web.config which specified the custom key store to use. You can skip this when using the default key store. Pay special attention to the keyContainerName attribute, it must match the name of the container created.
<!-- sets up the encrypted configuration to use a special container -->
<configProtectedData>
<providers>
<add name="MyCustomProvider"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
keyContainerName="MyCustomContainer"
useMachineContainer="true" />
</providers>
</configProtectedData>
To now encrypt the configuration file from the command line (you can easily embedd this into an msbuild/nant script), call the following command. Make sure the provider name passed in matches the provider name from the above configuration snippet. The following script will encrypt the connection string section:
aspnet_regiis -pef "connectionStrings" MyWebFilesDirectory -prov "MyCustomProvider"
The connection string section in the web.config file should now look like this:
<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>qDaaLdZtxtv1pbrXplfiHvUCKLq0ZpwJQorowmlm74QIH3ogcZyhNpYTgLCSNxaB4KaTLtcryRaivqPr+v/Lr6iv18d/VaIV1Ht0sCagA3sZCUQu/GuSTcTgfpQGdveU4Qsx5g4ERC/B8mQEwXtHs7a6VNVsYD4f6GFlO9g4iUI=</CipherValue>
</CipherData>
</EncryptedKey>
</KeyInfo>
<CipherData>
<CipherValue>lw9Y03jHQ6foqIAdN7UN0nOxc4y2zJ4ajb5dUjtxKyFa87vCmmMbBnTkatcoZ/6ZzibdEBg7Xmhf4SBqC4iCfQIgV5XIEb0j+P3gmDLSt+kC+enTLZGVlHt3ngND6dXJTF28C2jsVB2DIxI/u0p6cJ2UHRGfqvvetG24HnDPpZonlHuMGEyvKy/PhLf3OUv2Vc/v0aVi8srRwydjA1Ueqs9sGo+wGGqT1Leui3R/TCNiEwZrp1eO3Rt6W1NMEaRNkG3nz9tctHwOsNo9xiC+lM0IfGI/DFR04uwSzjuQX61Ph18nB+Q0zgcpauOsqRrNtorBSPqu+mfW8EL0bztU90T5F5i0TJ50BoXXo6F8kdTnJ1i90REFxsFBv/8jOXh++bUZMWRxnu3GUf+tJ5f7Kzr52GlApfkoMunTCLbd5zkPG8yga2iMJ+MGdqu9K2b+Qakpu8VNu6Ioo80l30Dbxw==</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
Register Keys on Web Farm
Register the key on all web servers running the application. First of all, create the container with the keys from the XML file created earlier:
C:\app> aspnet_regiis -pi MyCustomContainer mykeys.xml
Creating RSA Key container...
Succeeded!
Now the IIS application requires access to this container.
On Windows 2000, do this (assuming you’re not running IIS as a different user):
C:\> aspnet_regiis.exe -pa "MyCustomContainer" "ASPNET"
Adding ACL for access to the RSA Key container...
Succeeded!
On Windows 2003 and up, the following command shall work:
C:\> aspnet_regiis.exe -pa "MyCustomContainer" "NT AUTHORITY\NETWORK SERVICE"
Adding ACL for access to the RSA Key container...
Succeeded!
And that’s really it. Once the application with the encrypted web.config sections is deployed, IIS will automatically decrypt it.
Comments
3 Responses to “Encrypting web.config”
Leave a Reply
[...] Jochen Toppe’s Blog » Encrypting web.config [...]
One small (but important) change:
C:\app> aspnet_regiis -px MyCustomContainer mykeys.xml -pri
The -pri argument tells the machine that created the key store to also export the private key to the xml file. Without it, you only export the public key. Your procedure for importing and authorizing users remain the same.
aspnet_regiis will allow you to import just the public key, but you would only be able to use it to encrypt sections (not decrypt). If you encrypted your connection strings on the first server and installed just the public key on all the others, only the first server would be able to connect to the DB. The rest wouldn’t be able to parse the config.
aspnet_regiis creats a new key pair if you try to import just the Public key ..