Encrypting configuration files using protected configuration

One of the cool security features in ASP.NET 2.0 is the ability to parts of web.config. Web.config encryption uses XML encryption standards at its core.

Protected configuration uses a class derived from the abstract class ProtectedConfigurationProvider. .NET framework has shipped with two providers RSAProtectedConfigurationProvider which uses TripleDES and RSA encryption and DPAPIProtectedConfigurationProvider which uses Windows Data Protection API (DPAPI)

For more comprehensive information about this topic, please refer to MSDN

Protected configuration in action:

One of the most common uses of the protected configuration is to encrypt connection strings in web.confg (that's one of the reasons for creating a separate tag for connection strings instead of adding it in appSettings tag).

Let's say we have a connection string tag like this

<connectionStrings>

<add name="advWorks" connectionString="Data Source=.\yukon;Initial Catalog=AdventureWorks;User ID=webUser;pwd=my_P@ssw0rd" />

</connectionStrings>

Adding this connection string as plain text is not the best practice for web application security and this might cause serious hacking problems. To encrypt this tag only, you could use the encryption classes in .NET framework or use the handy tool ASPNet_regiis.exe.

Assuming that this application located in https://localhost/testwebCS2, we could use ASPNet_regiis.exe as following

aspnet_regiis -pe connectionStrings -app /testwebcs2

This line will use RSAProtectedConfigurationProvider to encrypt the tag connectionStrings in the application called /testwebCS2.

Then this tag would be as following (I omitted most of the cipher base64 strings to preserve space)

<connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider">

        <EncryptedData Type="https://www.w3.org/2001/04/xmlenc#Element"

            xmlns="https://www.w3.org/2001/04/xmlenc#">

            <EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#tripledes-cbc" />

            <KeyInfo xmlns="https://www.w3.org/2000/09/xmldsig#">

                <EncryptedKey xmlns="https://www.w3.org/2001/04/xmlenc#">

                    <EncryptionMethod Algorithm="https://www.w3.org/2001/04/xmlenc#rsa-1_5" />

                    <KeyInfo xmlns="https://www.w3.org/2000/09/xmldsig#">

                        <KeyName>Rsa Key</KeyName>

     </KeyInfo>

             <CipherData>

                    <CipherValue>YojkA1KgIR1nnThk=</CipherValue>

                    </CipherData>

                </EncryptedKey>

            </KeyInfo>

            <CipherData>

                <CipherValue>8h+tauv00O52DdGHFKSv =</CipherValue>

     </CipherData>

        </EncryptedData>

    </connectionStrings>

As you can see in the previous XML, the data itself encrypted using the symmetric encryption algorithm called Triple DES. The key used to encrypt the data is embedded but it's also encrypted using RSA.

But where's the key to decrypt that key?

Good question :). The RsaProtectedConfigurationProvider uses the machine account or the user account to encrypt the keys and save them in a file which called "key container". To use the protected configuration with ASP.NET we should not use the user account to encrypt the keys because we need to be logged in with that user to be able to open that key container.

Key container for the machine account usually saved in C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA. And the ASP.NET worker process identity (ASPNET user in XP/2000 or Network Service in case of 2003) should have access to these files to be able to decrypt it or you would get this error message

"Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened"

Fortunately the ASPNet_regiis tool gives us the option to add users to the ACL of the key containers using the –pa parameter.

For example to give access to the ASPNET user

aspnet_regiis -pa "<key container name>" "ASPNET"

So, how to get the key container name?

By searching in machine.config (usually in C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG) we would find this section

<configProtectedData defaultProvider="RsaProtectedConfigurationProvider">

    <providers>

      <add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false" />

      <add name="DataProtectionConfigurationProvider" type="System.Configuration.DpapiProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses CryptProtectData and CryptUnProtectData Windows APIs to encrypt and decrypt" useMachineProtection="true" keyEntropy="" />

    </providers>

  </configProtectedData>

The keycontainerName of the RsaProtectedConfigurationProvider is "NetFrameworkconfigurationKey" (it's good practice to change it in the production servers). So the aspnet_regiis would be as following

aspnet_regiis -pa "NetFrameworkConfigurationKey" "ASPNET"

What if I'm using a server farm?

In the server farms environment, you can simple use aspnet_regiis to create and export key container to distribute it to the whole server farm.

Comments

  • Anonymous
    November 17, 2005
    Thank you for a very clear description of the encryption procedure.

  • Anonymous
    March 20, 2006
    Really appreciate your help.
    I had was puzzled beyond 2 days by the problem:"Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened"
    now, it's solved.


  • Anonymous
    March 20, 2006
    I did all this but still get error: System.Configuration.ConfigurationErrorsException: Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened.

  • Anonymous
    March 21, 2006
    This has been resolved.  I had my servers mixed up.

    It was pointed out to me that the encryption and decryption must (at least in my case) take place on the same server. I was encrypting on one and then trying to decrypt on another.

    Mohamed, thanks for the fine article!

  • Anonymous
    March 27, 2006
    Great post and thanks for saving us from hours of debugging!

    We totally forgot the "-pa" part and your post seems to be a rare instance that actually mentions this critical step.

    Thanks again, PhiMix

  • Anonymous
    April 25, 2006
    Thank you for your help ...

  • Anonymous
    May 25, 2006
    Whenever i run the web application using the Debug mode the application works fine. When i create a virtual directory for the same and run it, it throws the "Container not found error" given in the article.

  • Anonymous
    June 15, 2006
    thanks so much, Very clear and Usefull !!

  • Anonymous
    August 09, 2006
    Mohamed, thanks for the great info. Like others, we were not doing the -pa step.

  • Anonymous
    August 15, 2006
    I have encrypted the connection string in web.config suffessfully. Now i want to read the connection string from my app. How do i decrypt from the code?

  • Anonymous
    September 01, 2006
    great article, i had the same problem , now its resolved

  • Anonymous
    October 16, 2006
    Good one. Thanks for the detailed info. I was struck up with this error. "Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened"

  • Anonymous
    October 18, 2006
    Great, finally an explanation. I'd just add the command for 2003: C:WINDOWSMicrosoft.NETFrameworkv2.0.50727>aspnet_regiis -pa "NetFrameworkConfigurationKey" "NT AuthorityNetwork Service" Thanks, Igor

  • Anonymous
    November 13, 2006
    Just make sure you do the -pe part first. Then the -pa part will work. I think this is because the -pe creates the KeyContainer, which must exist before you can authorize it with the -pa part. Great article, got me on the right track.

  • Anonymous
    December 19, 2006
    Hello, I have problems when I use a custom tag named gc.elmah I try to encrypt it but the system give me this error The configuration section 'gcelmah' was not found. can you help me with that. Best regards jaadrare@gmail.com

  • Anonymous
    December 26, 2006
    Hello, I get the error in the Visual Studio 2005 Cmd Prompt: The RSA key container was not found. I know that there is MachineKeys in the directory but it can not be read. Please help..

  • Anonymous
    January 15, 2007
    I get this error when trying to access my web service from a remote windows application. Should this work or do I need to specify a username and password? If yes, what u/p do I need to specify?

  • Anonymous
    January 25, 2007
    The comment has been removed

  • Anonymous
    February 05, 2007
    I followed the documentation on MSDN and I'm getting an error.  I've run all the aspnet_regiis commands to import the key pair (public & private) and grant access to the key pair.  The server is returning a "bad data" error when trying to decrypt the web.config.  Any ideas?

  • Anonymous
    February 11, 2007
    The comment has been removed

  • Anonymous
    February 11, 2007
    Oops! Managed to find from where the error popsup. I forgot to put -pri option when exporting the key to xml file. After doing it properly, it works just perfect. This is how you should export the key: aspnet_regiis -px "MyDataProtectionConfigurationProviderKey" tempmykeyfile.xml -pri

  • Anonymous
    February 11, 2007
    Here is a list of all steps I've done to encrypt two sections on my PC and then deploy it to the WebServer. Maybe it will help someone...:

  1. To create a machine-level RSA key container aspnet_regiis -pc "DataProtectionConfigurationProviderKeys" -exp
  2. Add this to web.config before connectionStrings section:  <configProtectedData>    <providers> <clear />      <add name="DataProtectionConfigurationProvider"           type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,                    Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,                    processorArchitecture=MSIL"           keyContainerName="DataProtectionConfigurationProviderKeys"           useMachineContainer="true" />    </providers>  </configProtectedData> Do not miss the <clear /> from above! Important when playing with encripting/decripting many times
  3. Check to have this at the top of Web.Config file. If missing add it: <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  4. Save and close Web.Config file in VS (very important!)
  5. In Command Prompt (my local PC) window go to: C:WINNTMicrosoft.NETFrameworkv2.0.50727
  6. Encrypt: (Be aware to Change phisical path for your App, or use -app option and give the name o virtual directory for app! Because I used VS on my PC I prefered the bellow option. The path is the path to Web.config file) aspnet_regiis -pef "connectionStrings" "c:BlaBlaBla" -prov "DataProtectionConfigurationProvider" aspnet_regiis -pef "system.web/membership" "c:BlaBlaBla" -prov "DataProtectionConfigurationProvider"
  7. To Decrypt (if needed only!): aspnet_regiis -pdf "connectionStrings" "c:BlaBlaBla" aspnet_regiis -pdf "system.web/membership" "c:BlaBlaBla"
  8. Delete Keys Container (if needed only!) aspnet_regiis -pz "DataProtectionConfigurationProviderKeys"
  9. Save the above key to xml file in order to export it from your local PC to the WebServer (UAT or Production) aspnet_regiis -px "DataProtectionConfigurationProviderKeys" tempmykeyfile.xml -pri
  10. Import the key container on WebServer servers: aspnet_regiis -pi "DataProtectionConfigurationProviderKeys" tempmykeyfile.xml
  11. Grant access to the key on the web server aspnet_regiis -pa "DataProtectionConfigurationProviderKeys" "DOMAINUser" See in IIS the ASP.NET user or use: Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name
  12. Remove Grant access to the key on the web server (Only if required!) aspnet_regiis -pr "DataProtectionConfigurationProviderKeys" "DomainUser"
  13. Copy and Paste to WebServer the encrypted Web.config file.
  • Anonymous
    February 13, 2007
    To solve the "The RSA key container could not be opened" error, create the key container using this command: aspnet_regiis -pc "NetFrameworkConfigurationKey" -exp

  • Anonymous
    February 18, 2007
    Can I use this technique to encrypt my application configuration file(WinForms application)? Or is it only applicable for ASP.Net? Can I encrypt withouht using aspnet_regiis? Thanks, Dharan

  • Anonymous
    March 29, 2007
    Thanks Mohamed, nice and succinct, just what the doctor ordered.

  • Anonymous
    April 01, 2007
    Hello Mohamed, Thanks for the article. But I have a problem encrypting my custom configuration section using aspnet_regiis. "Could not load file or assembly 'MyAssembly' or one of its dependencies. The system cannot find the file specified." It seems that aspnet_regiis doesn't search section handler assemblies in bin folder, because when I copied my assembly to C:WINDOWSMicrosoft.NETFrameworkv2.0.50727 it succeeded. Is there any way to make aspnet_regiis work? Thank you, Robert, robert@armsoft.am

  • Anonymous
    April 25, 2007
    Thanks for the useful explanation Mohamed. Sometimes these MS guys forget to give the "what if..." options in their explanations. Cheers, Orlando.

  • Anonymous
    May 15, 2007
    Thanks for the valuable info. i solved an issue using the info provided.

  • Anonymous
    May 24, 2007
    My case is little weired, I am getting following error occasionally for some of the users only, that too if same users access the web app after some time it works fine "Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened." What can be the reason for this one, this is really making me Mad....

  • Anonymous
    June 04, 2007
    I did try the encryption technique. It works fine on my machine, but when other try to use following is the error message they get. 'RsaProtectedConfigurationProvider'. Error message from the provider: Bad Data.

  • Anonymous
    June 07, 2007
    'RsaProtectedConfigurationProvider'. Error message from the provider: Bad Data. This error has been posted many times and nobody seems to have an answer. Please, if someone has an idea, i'll be great. Thanks

  • Anonymous
    October 17, 2007
    i am new to crytography and as a part of my project i am doing encryption using RSA algorithm in C++.i woul like to kno how we can encrypt files other than ordinary text files????

  • Anonymous
    January 24, 2008
    Please try this. I tried everything that was mentioned in this post, but nothing worked for me. I tried to use the DataProtectionConfigurationProvider and it worked for me. Using this provider will also reduce the call to apsnet_Regiis -pa .... aspnet_Regiis -pef system.web/identity . -prov DataProtectionConfigurationProvider Thanks, Vinayak

  • Anonymous
    February 12, 2008
    Was having the same problem with no solution until I ran across Seeni's comment above. I was using anonymous access and everything worked  after I passed the IUSR_machinename account using -pa Perhaps this advice can be added to the original article so less people overlook it ?

  • Anonymous
    May 08, 2008
    thank you for this post. it is really useful.

  • Anonymous
    June 03, 2008
    The comment has been removed

  • Anonymous
    July 16, 2008
    Thnx 4 the help, it really solved the problem of encrypting an specific part of the web.config. Be great and keep rockin' d-.-b

  • Anonymous
    September 08, 2008
    Is there a physical location or view where you can see what accounts/users have been granted access via the -pa switch?  Thus can you view that ACL somewhere?

  • Anonymous
    September 15, 2008
    Thanks Sharaf, i was put on the wall when i saw the error on my first attempt after implementing the encryption reading from different site, but your blog helped me resolve the same Thank you very much Shashidhar Rao. Lakkakula

  • Anonymous
    January 06, 2009
    I'm having the same problem as Makarand above...we've been running our encrypted web.config file for many months without problems. Suddenly, now we're getting Friday, May 25, 2007 3:09 AM by Makarand

re: Encrypting configuration files using protected configuration

My case is little weired, I am getting the error, ""Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. Error message from the provider: The RSA key container could not be opened." Decryption works some of time. It stops working and then works again for the same user even. I'm now running unencrypted just so the application is consistently available. I've reencrypted the file with the same intermittent error. Any ideas anyone?

  • Anonymous
    January 12, 2009
    Thank you very much for the nice Article and very useful solution. Thanks a TON... :)

  • Anonymous
    January 18, 2009
    hi..thanks for the useful info.My application needs to be deployed in a webserver where i dont have visual studio 2005 but .net framework 2.0 is installed.Can i get into Visual Studio Command Prompt to encrypt the config file in this machine? If so how?If not, is there any alter method for encryption.. Thank you for the help in advance…