I've been reading about encryption and decryption of certain parts of the web.config for C#/ASP applications and I am successful in encrypting the connectionstring of the web.config for my application. My problem is decrypting. I'm using the standard code to encrypt and decrypt but it modifies the web.config. Locally it works fine since when it does modify the web.config I can save it and it will still run but when I upload it to a remote server then it doesn't work.
The error I'm getting is
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
'RsaProtectedConfigurationProvider'. Error message from the provider:
Bad Data
Encrypting
try
{
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
ConfigurationSection section = config.GetSection("connectionStrings");
if (!section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection("RSAProtectedConfigurationProvider");
config.Save();
}
catch (Exception ex)
{
}
Decrypting
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section = config.GetSection("connectionStrings");
if (section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
config.Save();
}
I call the decrypting method whenever the page loads but it doesn't work and it gives me the error above.
I do not have access to the host server at all. So using the command line is not an option.
Make sure the same decryption key is available on the remote server that you have locally. This would be the machine key element.
You can create and export an RSA Key Container but you'll still need access to the remote server to import the container.
I don't believe that the machineKey element is relevant here BTW. From MSDN:
Key containers with local machine scope (useMachineContainer"true") are stored in a hidden folder at %ALLUSERSPROFILE%\Application Data\Microsoft\Crypto\RSA\MachineKeys
I'm guessing the scenario is you're trying to encrypt the web.config locally before pushing it to your hosting provider/remote server. Steve Rowbotham's answer on this question is correct in that you'll need the same RSA Key container on both your development machine and the remote server to be able to encrypt locally and decrypt remotely.
Can you take a different route and encrypt the web.config as part of your deployment process? We use MsDeploy to handle encrypting the config file during deployment and I can provide some sample code if you would like it.
Alternatively, when you application first loads (during the Application_Start event in global.asax) you could check if the connectionStrings section of the web.config is encrypted and then encrypt it. You shouldn't have to decrypt the web.config manually...
Related
I encypted the appconfig like this , on my computer works well but on a network doesn't work
Configuration config = ConfigurationManager.OpenExeConfiguration(exeConfigName);
ConnectionStringsSection section =
config.GetSection("connectionStrings")
as ConnectionStringsSection;
if (!section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection(
"DataProtectionConfigurationProvider");
config.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}
DataProtectionConfigurationProvider is machine-dependent. You can't encrypt it on your workstation and expect it to work on the server by default. You could use RsaProtectedConfigurationProvider and export the keys as needed. Or just encrypt it on the server itself.
See this related SO Question
I have an encrypted password in a connection string, contained in a web.config file. I do not know what the password is, and thus cannot connect to my database.
I ran aspnet_regiis.exe -pdf against the web.config and received the following:
Decrypting configuration section...
Succeeded!
I guess I had assumed that the password would be displayed on the screen, or something close to that? Then I thought the program might create a log file with the information in it? Couldn't find one.
I know I am missing something fundamental, I just don't know what it is.
You cannot decrpty the encrypted password.
The whole point of encrypting the password is so that no one is able to decrpty and find what the password is unless you know the key.
When you encrypt the connection string, the key is automatically created and stored in the machine where the encryption was done.
So, if you copy the web.config file to some other machine and do the decryption using:
aspnet_regiis.exe –pdf “connectionStrings” YourPathToWebConfigFile
This won't work.
And to answer your question, if the encryption and decryption was done on the same machine, then your web config file will change automatically with the plain text (decrypted data) for connection string , not that the password would be displayed on the screen.
Run below command
aspnet_regiis.exe –pdf “connectionStrings” C:\inetpub\wwwroot\MyApplication
C:\inetpub\wwwroot\MyApplication needs to be the path where your web.config file is. Once you finish executing above command check your web.config file. If it worked OK you will have decrepted connection string section.
I'm building an Azure Website-based solution that needs to periodically contact a Service Bus relay endpoint in the background. My planned design approach was to use an Azure WebJob as the execution engine for this background task -- I would store my Service Bus connection string with shared secret credentials in App.config, encrypt it using the Pkcs12ProtectedConfigurationProvider with my site's custom SSL certificate, and everything would work perfectly!
The only problem is, it appears that WebJobs are not able to access the certificates for their containing Websites. The code for my WebJob can be very simple (but note that the appSettings section of App.config is encrypted):
public static void Main()
{
string connectionString = ConfigurationManager.AppSettings["Microsoft.ServiceBus.ConnectionString"];
Console.WriteLine(connectionString);
}
If I import the site's certificate on my local machine and run the WebJob executable there, everything works as expected. But when I upload the ZIP file with my binaries and .exe.config file into Azure, the job always fails with the below error.
[07/18/2014 22:53:24 > 621d84: ERR ] Unhandled Exception:
System.Configuration.ConfigurationErrorsException: Failed to decrypt using provider 'Pkcs12Provider'.
Error message from the provider: No certificate was found for thumbprint <My Certificate's Thumbprint>
(C:\DWASFiles\Sites\<My Site Name>\Temp\jobs\triggered\<My Job Name>\hzcfdtn5.f22\WebJob.exe.Config line
XX) ---> System.ApplicationException: No certificate was found for thumbprint <My Certificate's Thumbprint>
Am I correct in surmising that a WebJob can't access the corresponding Website's certificate store? This would make it pretty much impossible to use the Pkcs12 provider to encrypt my WebJob's secrets -- is there a better option available? Or is a WebJob simply the wrong tool for this job?
Azure WebSites, AFAIK, cannot use custom certificates.
However, you can put the connection strings in the connection strings section of your website in the Azure Portal. Here are details on how to read it afterwards: http://azure.microsoft.com/blog/2013/07/17/windows-azure-web-sites-how-application-strings-and-connection-strings-work/
While the above will not solve the encryption problem, it would at least remove the CS from AppConfig. That's what we do with the Service Bus connection string for Azure WebJobs SDK http://azure.microsoft.com/blog/2014/06/18/announcing-the-0-3-0-beta-preview-of-microsoft-azure-webjobs-sdk/
A webjobs seems to be the right tool for what you are trying to do.
The code on the Site here (shown below) encrypts app.config. I ran this on a button press to encrypt my config.
When am i supposed to run the code - (e.g at application start-up in case it is not already encrypted)?
In my bin folder i have 2 xml configuration files (Applicationname.exe.config and Applicationname.vshost.exe - this code only encrypts the first one of them - When i deploy my program how do i ensure that the my customer doesn't accidentally get the unencrypted file also as this would be a major issue ?(Or does the windows installer take care of ensuring this)?
C# Code
Configuration config = ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.None);
SectionInformation appSettingsSecInfo = config.GetSection(
"appSettings").SectionInformation;
if (!appSettingsSecInfo.IsProtected)
{
Console.WriteLine("The configuration file has NOT been protected!");
// Encrypt this section by using security provider
// (RsaProtectedConfigurationProvider or DpapiProtectedConfigurationProvider).
appSettingsSecInfo.ProtectSection("RsaProtectedConfigurationProvider");
appSettingsSecInfo.ForceSave = true;
config.Save(ConfigurationSaveMode.Full);
}
Please follow steps at this page. Author of the code snippet that you reference also does mention this page. But he is wrong about it not working on app.config files. All you have to do is rename yourapp.exe.config file to web.config, encrypt the sections you want and rename back to yourapp.exe.config.
Now to your scenario. The page that I have referenced also states the following:
You can easily export and import RSA keys from server to server. This makes RSA encryption particularly effective for encrypting configuration files used on multiple servers in a Web farm.
And it has a section about exporting and importing RSA keys.
So you could encrypt the configuration on your PC, export RSA key used for encryption and put it in your installer. The installer would then import the RSA encryption key into machine or user store on PC on which the application is being deployed.
But you should realize that when the application is starting, encrypted configuration has to be decrypted using private part of RSA encryption key (that we imported or it originated on the PC). Therefore if the application can get access to the private key so might the customer (I presume that the customer has physical access to the PC with your application). What you could do is use a user key container of user that only the application will run under for RSA encryption key but if the customer has administrator rights you will not be able to forbid him from decrypting the configuration.
So much for standard solutions. But you can always put sensitive data in a custom xml file, encrypt it and the encryption key compile into you application. Then the application would have to implement a logic to decrypt the xml itself. The customer would have to decompile your application to get to the RSA encryption key.
I want to encrypt my "ConnectionString" settings which is located in app.config.
But at the Runtime, I want to use( read ConnectionString ) it directly, without decrypt it.
I mean, I don't want to anyone to decrypt the string. There should be NO decryption method.
I'm thinking; it should be like embed .net/asp.net/iis feature to use.
Like "Windows Login" ( you can enter it, use it, but you can't decrypt )
===
An Example Usage; You have small website with some critical data.
You have no money to buy private server,
so you are working on shared server, if the server hacked somehow,
you application and database will be stolen.
But if you put encrypted connectionstring in app.config,
This will be hard to decrpt it and see what is inside in Database.
Encrypting and decrypting configuration settings in a config file can be done from the command line using the aspnet_regiis.exe tool.
The details are described in the following MSDN article:
Encrypting and Decrypting Configuration Sections
As the tool is mainly intended to be used with Web applications, it expects the config file to be named 'web.config'. This means that you temporarily will have to rename your app.config file to web.config:
rename App.config web.config
aspnet_regiis -pef connectionStrings . -prov DataProtectionConfigurationProvider
rename web.config App.config
DPAPI might be a solution.
You can connect your usr/pwd/credentials to the machine. JGalloway knows more about this than I. JGalloway knows more about anything dotnet than I.
http://weblogs.asp.net/jgalloway/archive/2008/04/13/encrypting-passwords-in-a-net-app-config-file.aspx
If I haven't mixed things up this creates a usr/pwd combination that is bound to the very hardware of the machine. I.e. change network card and stuff might break. Also; one cannot create the usr/pwd/creds one machine and then transfer to another. In short this means that you have to do whatever you have to do on the production machine - might give you a headache if you are targeting continuous delivery.
Caveat: I haven't tried it myself. Instead I opted for a "regular" encryption. If someone got hold of my encrypted string and bytecode and reverse engineered it I would be smoked. But it was enough of security for me.