Signing app.config
Categories
The System.Configuration.ProtectedConfigurationProvider class conceptually allows you to "protect" a node in a .net config file. The quotes here are important if I'm going to weasel my line of thinking in.
Of course, ProtectedConfigurationProvider is an abstract class. The two implementations shipped with .net include DpapiProtectedConfigurationProvider and RsaProtectedConfigurationProvider, the first using DPAPI to "protect" a node using a key which is specific to a particular machine. The second uses rsa keys, which can be installed on different machines.
Here we see the first problem. This technique is really intended for machines that you have control over, i.e. web.config files. In fact, the way you set up protection is with aspnet_regiis.
But what if you want to protect config files on the client - app.config files? You can't use the DPAPI class, because you need to encrypt it on the machine and for the user who's going to use it. You could use the rsa class, but then you need to install rsa keys; not necessarily a bad thing, but potentially inconvenient.
Let's look at those quotes around "protect". Clearly, in the classes that are used, protect means encryption. What if all we want to do is sign a node? We might have information that isn't sensitive, but that we don't really want changed - WCF configuration perhaps, and the security settings of a service. Or even something as prosaic as how often to call a web service. We probably don't want to have that hard coded, but we don't want just anyone to change it. (Of course, these examples are just to stop casual hacking (in the old skool use of the word) and changing the behaviour of our app, rather than have them develop something that could attack us.)
This does kind of subvert how the ProtectedConfigurationProvider is currently used, but does fit with the name - we are protected the node, after all. It doesn't necessarily help that the methods on PCP are Encrypt and Decrypt, but we can quite happily look the other way for something like that. At least we'd be safe in the knowledge that we're not subverting it as much as this Wrox article, which uses a custom protection provider to redirect config to a database.
This codeproject article is the only link I've found about protecting application config files. It highlights some interesting problems, not least of which is having to distribute the config file unprotected, and protecting it at install time.
I reckon I could write a custom provider that would be able to sign a configuration node. It'd still need a public key, but perhaps that could be embedded in the (signed) executable, rather than needing to be installed in the Certificate Store. The node would be wrapped in an XML-Signature envelope, the Decrypt method would just check the signature, throw a ConfigurationErrorsException if it's invalid or return the inner xml if everything's ok. Of course, since the content is in there in plain text, it would be dead easy to remove the signature envelope and the provider attribute and just have an unprotected node. The way round this is to have the code check that certain nodes' SectionInformation.IsProtected property is true, and fail if not.
I've still not 100% convinced this is actually worthwhile. Would it be simpler (if overkill) to just encrypt the sections? Is there a way to do this without using a protection provider, such as signing the entire file (I don't know where the signature would live in this case, or how to canonicalise the file)?
And the 64 million dollar question - am I just being paranoid about the need to sign config files? Is there any real config that I wouldn't want a customer to change? Is there actually anything you can set in the WCF config that would give me problems? Do I really want to have a config file that the customer can't configure?