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 http://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="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>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 (42)

  1. Jim Carlson says:

    Thank you for a very clear description of the encryption procedure.

  2. jinglecat says:

    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.

  3. Phil says:

    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.

  4. Phil says:

    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!

  5. PhiMix says:

    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

  6. Gaurav Grover says:

    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.

  7. Sailer, Leonardo says:

    thanks so much, Very clear and Usefull !!

  8. Mohamed, thanks for the great info. Like others, we were not doing the -pa step.

  9. vj says:

    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?

  10. Shan says:

    great article, i had the same problem , now its resolved

  11. Manjunath says:

    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"

  12. Igor says:

    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

  13. Ed C says:

    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.

  14. Javier Ralda says:

    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

  15. Ozgur says:

    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..

  16. Neil says:

    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?

  17. Seeni says:

    Thanks for the great info.

    Additional note – For the -pa the account should be the user account that the current thread will execute under.

    If idenity impersonate is false in web.config and site is running under anonymous mode enabled, then IUSR_MachineName account should be passed as account (or whichever account is used as anonymous user account).

    If impersonate is true in web.config and windows authentication is enabled (as the only checked option in Directory Security of IIS Admin tool), then the actual end user’s account should be passed as account to -pa command. Or generally you can pass "NT AuthorityAuthenticated Users" as the account name to allow all authenticated users.

  18. Matthew P says:

    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?

  19. Naica says:

    I’ve done all the required steps, even the grant access to the key, still have this error:

    Configuration Error

    Description: An error occurred during the processing of a configuration file required to service this request. Please review the specific error details below and modify your configuration file appropriately.

    Parser Error Message: Failed to decrypt using provider ‘MyProtectionConfigurationProvider’. Error message from the provider: Bad Data.

    Source Error:

    Line 59:   </configProtectedData>

    Line 60:   <connectionStrings configProtectionProvider="MyProtectionConfigurationProvider">

    Line 61:     <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element&quot;

    Line 62:       xmlns="http://www.w3.org/2001/04/xmlenc#"&gt;

    Line 63:       <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc&quot; />

  20. Naica says:

    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

  21. Naica says:

    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"&gt;

    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.

  22. John Abbott says:

    To solve the "The RSA key container could not be opened" error, create the key container using this command:

    aspnet_regiis -pc "NetFrameworkConfigurationKey" -exp

  23. Dharan Prakash says:

    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

  24. Owen O'Flaherty says:

    Thanks Mohamed, nice and succinct, just what the doctor ordered.

  25. Robert says:

    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

  26. orlando mendez says:

    Thanks for the useful explanation Mohamed. Sometimes these MS guys forget to give the "what if…" options in their explanations.

    Cheers,

    Orlando.

  27. Anu says:

    Thanks for the valuable info.

    i solved an issue using the info provided.

  28. Makarand says:

    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….

  29. Vivek says:

    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.

  30. Ernesto says:

    ‘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

  31. seban says:

    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????

  32. vinayakg says:

    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

  33. Shawn says:

    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 ?

  34. Sun says:

    thank you for this post. it is really useful.

  35. mukesh says:

    Hi

    will i have to use command line tool(aspnet_regiis)for encrypting and exporting RSA keys?

    Is there any way to use any c# code for this?

  36. kominsky says:

    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

  37. Chris says:

    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?

  38. Shashidhar says:

    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

  39. Joyce says:

    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?

  40. Abhijeet says:

    Thank you very much for the nice Article and very useful solution.

    Thanks a TON… 🙂

  41. kranthi.babu says:

    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…

Skip to main content