In the following example I protect the "DemoWinApp.Properties.Settings" section of the "Sleutels.config" file.
private static void toggleProtectionSleutelsConfig()
{
var fileMap = new ConfigurationFileMap(@"D:\Experimenten\ReadProtectedConfigFile\Sleutels.config");
var configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
var sectionGroup = configuration.GetSectionGroup("applicationSettings"); // This is the section group name, change to your needs
var section = (ClientSettingsSection)sectionGroup.Sections.Get("DemoWinApp.Properties.Settings"); // This is the section name, change to your needs
var setting = section.Settings.Get("SecretMessage"); // This is the setting name, change to your needs
Console.WriteLine(setting.Value.ValueXml.InnerText);
// Toggle beveiliging
if (!section.SectionInformation.IsProtected)
{
//Protecting the specified section with the specified provider
section.SectionInformation.ProtectSection("RSA");
}
else
{
section.SectionInformation.UnprotectSection();
}
section.SectionInformation.ForceSave = true;
configuration.Save(ConfigurationSaveMode.Modified);
Console.ReadKey();
}
The contents of the "Sleutels.config" file is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, 
 System, Version=2.0.0.0, Culture=neutral, 
 PublicKeyToken=b77a5c561934e089">
<section name="DemoWinApp.Properties.Settings" type="System.Configuration.ClientSettingsSection,
System, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<DemoWinApp.Properties.Settings>
<setting name="SecretMessage" serializeAs="String">
<value>This is the secret message.</value>
</setting>
</DemoWinApp.Properties.Settings>
</applicationSettings>
<configProtectedData>
<providers>
<add name="RSA"
type="System.Configuration.RsaProtectedConfigurationProvider, System.Configuration, Version=2.0.0.0,
 Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
 processorArchitecture=MSIL"
keyContainerName="RobinsKeys"
useMachineContainer="true" />
</providers>
</configProtectedData>
</configuration>
After running the code the "Sleutels.config" file is encrypted and a RSA key container is created in C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys
If I try to export the RSA key container with the commandline:
c:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis -pc "RobinsKeys" –exp
Then I get the error message:
Exporting RSA Keys to file...
Key not valid for use in specified state.
This means that the RSA Key container is not marked as "exportable". If you would create an key container with the command line, then there is an optional parameter "-exp" to mark the key as exportable.
For example: aspnet_regiis -pc "RobinsKeys" -exp
Is this -exp
option also available while using the section.SectionInformation.ProtectSection("RSA");
method in code or as an configuration option in the RSA provider section in the "Sleutels.config" configuration file?
Any help is appreciated!
To summarize the discussion, you need to create a RSA crypto container programmatically before you can use it to store RSA keys.
The reason is that the RSAProtectedConfigurationProvider
doesn't have an option to make the automatically created RSA key container exportable.
As you wrote in the chat, this workaround can be achieved by the following example code (I've added some output to the console, RSA parameters printed are explained here):
void Main()
{
// Create the CspParameters object and set the key container
// name used to store the RSA key pair.
var cp = new System.Security.Cryptography.CspParameters();
cp.Flags = System.Security.Cryptography.CspProviderFlags.UseMachineKeyStore;
cp.KeyContainerName = "RobinsKeys";
// Create a new instance of RSACryptoServiceProvider that accesses
// the key container MyKeyContainerName.
// If it is not already there, it will create a new one, which is exportable.
var myRSA = new System.Security.Cryptography.RSACryptoServiceProvider(cp);
// print it on console
Console.WriteLine($"=== Container: {cp.KeyContainerName} ===");
Console.WriteLine(myRSA.ToXmlString(true).Replace("><", ">\n<"));
}
which can be read in more detail here. The link provided also shows how to
It might be useful to get a list of containers, this is discussed in a separate question.
Some more information about key containers you can find in this Microsoft article, also about available aspnet_regiis
parameters.
Once a RSA container is created, it can be used by IIS. It is important to understand the difference between user-level and machine-level key containers, which is described in this documentation.
Kindly let me know if anything is missing from the discussion, and I will update this answer.