How do I encrypt user.settings - c#

I'm developing a windows desktop application with C# .NET4.0 VS2010 on Windows 8.1. I've a range of settings that I store using the .NET settings mechanism. These have user scope so, when set within the application they are written to Users\username\AppData\Local\companyname\App.exe_URL_randomstuff\versionno\user.config.
These settings include some user registration information that I need to keep hidden. My research suggests that I should be able to encrypt settings using an RsaProtectedConfigurationProvider but all the examples I've found for this relate to encrypting app.config rather than user.config (e.g. http://msdn.microsoft.com/en-us/library/system.configuration.rsaprotectedconfigurationprovider.aspx).
My question therefore is can user.config be encrypted and if so how? I note that when I instance a System.Configuration.Configuration object I can set the ConfigurationUserLevel to PerUserRoamingAndLocal. When I examine the object via the debugger it seems to be refering to the correct user.config file but when I go on to instance a ConfigurationSection to protect it returns null. The code looks like this:
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.PerUserRoamingAndLocal);
ConfigurationSection connStrings = config.AppSettings;
connStrings.SectionInformation.ProtectSection(provider);
I'm thinking that config.AppSettings is probably not correct but I'm not sure what to replace it with.
Any advice greatly appreciated.

Got it working now. I was correct to be using ConfigurationUserLevel.PerUserRoamingAndLocal to access my user.config file. The problem was with config.AppSettings. I was on the right track replacing this with config.GetSection("Progname.Properties.Settings") but I got the naming wrong. The working code now is as follows:
System.Configuration.Configuration config =
ConfigurationManager.OpenExeConfiguration(
ConfigurationUserLevel.PerUserRoamingAndLocal);
ConfigurationSection connStrings = config.GetSection("userSettings/Progname.Properties.Settings");
connStrings.SectionInformation.ProtectSection(provider);
"Progname" is whatever your assembly is called. Thanks to #neoistheone and #hatchet for your input.

Related

Modify appSettings section of web.config file programatically [duplicate]

I am confused on how to modify the web.config appSettings values at runtime. For example, I have this appSettings section:
<appSettings>
<add key="productspagedesc" value="TODO: Edit this default message" />
<add key="servicespagedesc" value="TODO: Edit this default message" />
<add key="contactspagedesc" value="TODO: Edit this default message" />
<add key="aboutpagedesc" value="TODO: Edit this default message" />
<add key="homepagedesc" value="TODO: Edit this default message" />
</appSettings>
Let's say, I want to modify the "homepagedesc" key at runtime. I tried ConfigurationManager and WebConfigurationManager static classes, but the settings are "read-only". How do I modify appSettings values at runtime?
UPDATE:
Ok, so here I am 5 years later. I would like to point out that experience has told me, we should not put any configuration that intentionally is editable at runtime in the web.config file but instead we should put it in a separate XML file as what one of the users commented below. This will not require any of edit of web.config file to restart the App which will result with angry users calling you.
You need to use WebConfigurationManager.OpenWebConfiguration():
For Example:
Dim myConfiguration As Configuration = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~")
myConfiguration.ConnectionStrings.ConnectionStrings("myDatabaseName").ConnectionString = txtConnectionString.Text
myConfiguration.AppSettings.Settings.Item("myKey").Value = txtmyKey.Text
myConfiguration.Save()
I think you might also need to set AllowLocation in machine.config. This is a boolean value that indicates whether individual pages can be configured using the element. If the "allowLocation" is false, it cannot be configured in individual elements.
Finally, it makes a difference if you run your application in IIS and run your test sample from Visual Studio. The ASP.NET process identity is the IIS account, ASPNET or NETWORK SERVICES (depending on IIS version).
Might need to grant ASPNET or NETWORK SERVICES Modify access on the folder where web.config resides.
Changing the web.config generally causes an application restart.
If you really need your application to edit its own settings, then you should consider a different approach such as databasing the settings or creating an xml file with the editable settings.
And if you want to avoid the restart of the application, you can move out the appSettings section:
<appSettings configSource="Config\appSettings.config"/>
to a separate file. And in combination with ConfigurationSaveMode.Minimal
var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
config.Save(ConfigurationSaveMode.Minimal);
you can continue to use the appSettings section as the store for various settings without causing application restarts and without the need to use a file with a different format than the normal appSettings section.
2012
This is a better solution for this scenario (tested With Visual Studio 2008):
Configuration config = WebConfigurationManager.OpenWebConfiguration(HttpContext.Current.Request.ApplicationPath);
config.AppSettings.Settings.Remove("MyVariable");
config.AppSettings.Settings.Add("MyVariable", "MyValue");
config.Save();
Update 2018 =>
Tested in vs 2015 - Asp.net MVC5
var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
config.AppSettings.Settings["MyVariable"].Value = "MyValue";
config.Save();
if u need to checking element exist, use this code:
var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");
if (config.AppSettings.Settings["MyVariable"] != null)
{
config.AppSettings.Settings["MyVariable"].Value = "MyValue";
}
else { config.AppSettings.Settings.Add("MyVariable", "MyValue"); }
config.Save();
I know this question is old, but I wanted to post an answer based on the current state of affairs in the ASP.NET\IIS world combined with my real world experience.
I recently spearheaded a project at my company where I wanted to consolidate and manage all of the appSettings & connectionStrings settings in our web.config files in one central place. I wanted to pursue an approach where our config settings were stored in ZooKeeper due to that projects maturity & stability. Not to mention that fact that ZooKeeper is by design a configuration & cluster managing application.
The project goals were very simple;
get ASP.NET to communicate with ZooKeeper
in Global.asax, Application_Start - pull web.config settings from ZooKeeper.
Upon getting passed the technical piece of getting ASP.NET to talk to ZooKeeper, I quickly found and hit a wall with the following code;
ConfigurationManager.AppSettings.Add(key_name, data_value)
That statement made the most logical sense since I wanted to ADD new settings to the appSettings collection. However, as the original poster (and many others) mentioned, this code call returns an Error stating that the collection is Read-Only.
After doing a bit of research and seeing all the different crazy ways people worked around this problem, I was very discouraged. Instead of giving up or settling for what appeared to be a less than ideal scenario, I decided to dig in and see if I was missing something.
With a little trial and error, I found the following code would do exactly what I wanted;
ConfigurationManager.AppSettings.Set(key_name, data_value)
Using this line of code, I am now able to load all 85 appSettings keys from ZooKeeper in my Application_Start.
In regards to general statements about changes to web.config triggering IIS recycles, I edited the following appPool settings to monitor the situation behind the scenes;
appPool-->Advanced Settings-->Recycling-->Disable Recycling for Configuration Changes = False
appPool-->Advanced Settings-->Recycling-->Generate Recycle Event Log Entry-->[For Each Setting] = True
With that combination of settings, if this process were to cause an appPool recycle, an Event Log entry should have be recorded, which it was not.
This leads me to conclude that it is possible, and indeed safe, to load an applications settings from a centralized storage medium.
I should mention that I am using IIS7.5 on Windows 7. The code will be getting deployed to IIS8 on Win2012. Should anything regarding this answer change, I will update this answer accordingly.
Who likes directly to the point,
In your Config
<appSettings>
<add key="Conf_id" value="71" />
</appSettings>
in your code(c#)
///SET
ConfigurationManager.AppSettings.Set("Conf_id", "whateveryourvalue");
///GET
string conf = ConfigurationManager.AppSettings.Get("Conf_id").ToString();
Try This:
using System;
using System.Configuration;
using System.Web.Configuration;
namespace SampleApplication.WebConfig
{
public partial class webConfigFile : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
//Helps to open the Root level web.config file.
Configuration webConfigApp = WebConfigurationManager.OpenWebConfiguration("~");
//Modifying the AppKey from AppValue to AppValue1
webConfigApp.AppSettings.Settings["ConnectionString"].Value = "ConnectionString";
//Save the Modified settings of AppSettings.
webConfigApp.Save();
}
}
}

C# Windows form application - Save configuration during installation / Use external config

Before I begin, I've done good bit of research and googling. I think I didn't find the perfect answer because I'm probably a noob :)
However, I've created a POS software using Windows C# form application and it's working perfectly fine. Now, this application is using MySQL as database server.
I've been hard-coding the database server credentials on app.config file.
Code for the app.config file :
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="cString" connectionString="Server=localhost;Database=adittoenterprise;port=3306;Uid=root;Pwd=root123" providerName="MySql.Data.MySqlClient"/>
</connectionStrings>
</configuration>
Now I'm trying to create a package for other users to use. Definitely I need to come up with solution where the user can provide
host
username
password
During the installation and the application should store this somewhere (that is where my knowledge is lacking) and use it on the run time.
Any alternative solution is most welcome.
Thanks everyone in advance for bearing with me and helping me :)
Your installer needs to modify the app.config file. There are many different types of installers available and some of the more fully-featured packages can modify XML files such as app.config during installation.
It's also possible to modify the connection string at runtime (though since it's an application-scope setting, not a user-scope setting, that's probably not a good idea) as long as you do it before any database objects attempt to use it:
Properties.Settings.Default["cString"] = "new connection string";
... so you could potentially distribute your app.config with a blank connection string and prompt the user to provide those values the first time the application is run. You'd have to save the new value into a user-scope setting, though, in order for Save() to work:
Properties.Settings.Default.CustomConnectionString = "new connection string";
Properties.Settings.Default.Save();
(Note that I am a computer science student and still learning)
EDIT the links are not useful for your case as they only work with IIS, but still I would not save passwords in plaintext to a file such as the other answer suggested.
It should be considered bad practice to save the password especially plain text. Usually if an application starts it would require the user to authenticate to get access to the database. Of course you can store the password, but doing that properly you should look at http://msdn.microsoft.com/en-us/library/hh8x3tas.aspx and http://msdn.microsoft.com/en-us/library/89211k9b%28v=vs.80%29.aspx
Then if your application start for the first time your application can create/edit the config file and store the values. Note that your application cannot change it's own app.config at runtime so it would make sense to create a web.config for you database connection.

How to encrypt app.config ( Without decrypt method )

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.

Reload configuration settings from an external config file during run-time

I'm writing a game server in C# and would like to reload or refresh settings from a config file while the server is running.
Ideally I would like to save the settings in an XML file, have the ability to edit
the file while the game server is running and then send the server the command to reload
the settings from the file.
I know I can use a database to do this as well, but the game server is fairly small and I think it would be more practical to just save settings in a flat-file. I will have file-level access to the machine the server will run on.
What should I use?
Use http://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.aspx
Use a Custom Configuration Section, hookup the sections from the app.config to external config file(s) by setting the location attrib of the section. All xml loading and serialization is done by those custom classes
Code provided by CarelZA:
First of all, ConfigurationManager caches the application's configuration by config section, and you can call ConfigurationManager.RefreshSection() to invalidate the cache for a specific section.
In app.config I added:
<configSections>
<section name="gameSettings"
type="System.Configuration.NameValueSectionHandler,system , Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, Custom=null"/>
</configSections>
<gameSettings configSource="game.config"/>
I created a file called "game.config" and set "Copy to Output Directory" to "Copy always".
In game.config:
<gameSettings>
<add key="SettingName" value="SettingValue" />
</gameSettings>
Then in code, in order to access any setting:
settings = (NameValueCollection) ConfigurationManager.GetSection("gameSettings");
return settings["SettingName"];
And to reload the game config at any time when the reload command is sent to the server:
ConfigurationManager.RefreshSection("gameSettings");
As per request posting my comment as an answer:
You can set it up so the server auto-loads the file settings with FileSystemWatcher. If you use a custom Settings class, you can simply lock the class, reload it from a file and unlock it (if you are using multiple threads).
Reading/writing from/to file or serialization is so trivial in .NET that that is probably not what you need help with and there are many options how to do it.
Sounds like a job for XML Serialization! Instead of manually parsing and editing XML, you can easily achieve this same effect by creating a settings object, serializing it to XML, and de/serializing it when you need to make modifications. This way, you could hot swap configuration files.
using System.Xml.Serialization;
For instance, you could have the object
public class Settings
{
public string SomeProperty {get; set;}
public string SomeProperty2 {get; set;}
}
Save it to your disk as,
var settings = new Settings {SomeProperty="Hello", SomeProperty2="Joe"};
var fs = new FileStream("settings.xml");
var xs = new XmlSerializer(settings.GetType());
xs.Serialize(fs,settings);
Read it back in as,
var fs = new FileStream("settings.xml");
var settings = (Settings)fs.Deserialize(fs);
Check out the MemoryCache in System.Runtime.Caching (.NET 4.0). You could write yourself a simple class which performs the following steps:
Load the XML file
Parse its contents into whatever representation you want them in
Store the output in the cache with a HostFileChangeMonitor watching it - this will cause it to be removed from the cache automatically when the file is changed
Before performing any of the above, you'd check the cache to see if a previously-cached copy of the settings exists and only proceed if it doesn't.
The advantage of rolling your own approach like this is that you do not trigger restarts of the application as is the case with AppSettings stored in your web.config or app.config files. (It should be said that this is not the only way of achieving this)

How to Encrypt a portion of AppConfig file in any win form application?

I am working on a small winform application. Here i am having some configuration settings e.g. User Name and password kinda stuff.
Now my requirement is that i want to encrypt this particular detail. So can somebody tell me as how this can be done in .NET (C#).
You can use RsaProtectedConfigurationProvider http://msdn.microsoft.com/en-us/library/system.configuration.rsaprotectedconfigurationprovider.aspx
You can encrypt sections of your app.config using DPAPI provider. Put your username/pwd pair in appSettings section. Nothing else need to change in your application. you still keep reading appsettings strings as usual. Use this code below to encrypt/decrypt parts of your config file.
//call: ProtectSection("appSettings","DataProtectionConfigurationProvider");
private void ProtectSection(string sectionName, string provider)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && !section.SectionInformation.IsProtected)
{
section.SectionInformation.ProtectSection(provider);
config.Save();
}
}
//call: UnProtectSection("appSettings");
private void UnProtectSection(string sectionName)
{
Configuration config =
WebConfigurationManager.
OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection section = config.GetSection(sectionName);
if (section != null && section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
config.Save();
}
}
This article on Code Project describes how to encrypt and decrypt strings. It's a class you call, but the source code is provided so you can see how it works.
This article on Sharper Tutorials actually covers the case of encrypting a connection string.
Unfortunately both are too long to quote here.
There is build-in support for encrypting configuration files for ASP.NET applications using Windows Data Protection API but I have never tried if this can be applied to App.config, too. The advantage of this is that the keys are stored in a key store under control of the operating system.
Besides this I am not aware of any other build-in solutions and we usually do decryption ourself after reading the encrypted values. This requires to store a key somewhere - usually included in the code - and is far from optimal. Therefore if possible one should use Windows integrated security (SQL Sever authentication for example is deprecated) or any other advanced infrastructure like Kerberos if available.

Categories

Resources