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, PhiMixAnonymous
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 resolvedAnonymous
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, IgorAnonymous
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.comAnonymous
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 removedAnonymous
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 removedAnonymous
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 -priAnonymous
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...:
- To create a machine-level RSA key container aspnet_regiis -pc "DataProtectionConfigurationProviderKeys" -exp
- 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
- Check to have this at the top of Web.Config file. If missing add it: <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
- Save and close Web.Config file in VS (very important!)
- In Command Prompt (my local PC) window go to: C:WINNTMicrosoft.NETFrameworkv2.0.50727
- 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"
- To Decrypt (if needed only!): aspnet_regiis -pdf "connectionStrings" "c:BlaBlaBla" aspnet_regiis -pdf "system.web/membership" "c:BlaBlaBla"
- Delete Keys Container (if needed only!) aspnet_regiis -pz "DataProtectionConfigurationProviderKeys"
- 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
- Import the key container on WebServer servers: aspnet_regiis -pi "DataProtectionConfigurationProviderKeys" tempmykeyfile.xml
- 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
- Remove Grant access to the key on the web server (Only if required!) aspnet_regiis -pr "DataProtectionConfigurationProviderKeys" "DomainUser"
- 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" -expAnonymous
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, DharanAnonymous
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.amAnonymous
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. ThanksAnonymous
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, VinayakAnonymous
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 removedAnonymous
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-.-bAnonymous
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. LakkakulaAnonymous
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…