How to encrypt / decrypt a configuration file section with RsaProtectedConfigurationProvider

18,762

First you need to understand how and from what configuration encryption really protects you. RsaProtectedConfigurationProvider can store private keys which are used for actual encryption in two places. First one is

C:\Documents and Settings\All Users\Application Data\Microsoft\Crypto\RSA\MachineKeys

This is folder to store machine-wide keys. By default, any user can access this folder but you need to be elevated (run as admin) to read files in this folder (again, by default).

Second possible location is

C:\Documents and Settings\[user name]\Application Data\Microsoft\Crypto\RSA

This is user-level location - only specific user can access it.

By default, RsaProtectedConfigurationProvider will use machine-level location, this is controlled by UseMachineContainer property of this provider. Default configuration is defined in machine-level configuration file (located at C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config) and defined like this:

<add name="RsaProtectedConfigurationProvider" type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" description="Uses RsaCryptoServiceProvider to encrypt and decrypt" keyContainerName="NetFrameworkConfigurationKey" cspProviderName="" useMachineContainer="true" useOAEP="false"/>

If you would like to encrypt your section using user-level location, you can override this configuration in your own app.config file (see more here).

Now when you know all that, you can make an informed decision whether you need to encrypt your section and if yes - which location to use.

  1. If you use machine-level location (default) - your applicaton should be run elevated (under admin) both for encryption and decryption of your section. If someone will get access to your configuration file - he will not be able to decrypt it without having admin permissions. Running elevated might be a problem in some environments (especially corporate).

  2. If you use user-level location - your applicaton does not require to run elevated. Only user which encrypted section can later decrypt it. If someone gets access to your computer under different user (imagine some corporate domain) and steals a file - he won't be able to decrypt it.

You can either pre-encrypt your section for specific user\machine (keys with which sections are encrypted can be exported from one machine to another if necessary) or on first run ask user to type sensitive data (password to the database as an example) - then save that data to app.config and encrypt section.

As for why you get decrypted value automatically - that is because it's decrypted on the fly if possible. You are running as admin by default it seems (have your UAC disabled for example) so you can access keys which were used for encryption and so can decrypt. If you ran without admin - it will throw exception when you try to access encrypted value.

Share:
18,762
FieryA
Author by

FieryA

Updated on June 07, 2022

Comments

  • FieryA
    FieryA almost 2 years

    In my config file, i have some sensitive informations i wanted to encrypt for more security.

    This is my code ( working as expected ):

    class Program
    {
        static void Main(string[] args)
        {
            System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = @"D:\Web_S\Prep\test\test.exe.config";
            System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            string userNameWithoutEncryption = configuration.AppSettings.Settings["username"].Value;
            EncryptAppSettings("appSettings", configuration);
        }
    
        protected static void EncryptAppSettings(string section, Configuration configuration)
        {    
            AppSettingsSection objAppsettings = (AppSettingsSection)configuration.GetSection(section);
            objAppsettings.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider");
            objAppsettings.SectionInformation.ForceSave = true;
            configuration.Save(ConfigurationSaveMode.Modified);
    
        }
    }
    

    .config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <appSettings>
        <add key="username" value="a2zmenu"/>
        <add key="password" value="password"/>
      </appSettings>
    </configuration>
    

    The .config encrypted looks like this :

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <configSections>
        <section name="customAppSettings" type="System.Configuration.NameValueSectionHandler" />
      </configSections>
      <appSettings configProtectionProvider="RsaProtectedConfigurationProvider">
        <EncryptedData Type="http://www.w3.org/2001/04/xmlenc#Element"
          xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#tripledes-cbc" />
          <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
            <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
              <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
              <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
                <KeyName>Rsa Key</KeyName>
              </KeyInfo>
              <CipherData>
    <CipherValue>09+Lm23xDWWnAZFOagh3NRwp5tzad+3oedvTgoeWqunQBiAfk9UGfGxriZg6snwwANUDzOANZ+wOFUb6qa0Atf
    NgSd6b4FFSKTqzkfLlk+S9GtPSAVrRaLU9
    /Q2Qu7oxoSbhW7NWtengJbEZrFm+GqlLlm08w8Np/y03DMExFeA=</CipherValue>
              </CipherData>
            </EncryptedKey>
          </KeyInfo>
          <CipherData>
    <CipherValue>qSYRXNEKhbwNodH60c7qoWeKZ2QKVQmizPXVGCgHVZPMQ4F+XDqlZa2OyIin0kEI3j8pCjNL097RlZClgdd
    gPEd61AEw6DXJc43Z98obNFHmXfK9aS67qEtO6E
    T+qCWQq2ZRbfK6xZ6jlfeink35/veUmoxAmDXrkwdrbQVKv98=</CipherValue>
          </CipherData>
        </EncryptedData>
      </appSettings>
    </configuration>
    

    I have the following questions: Is it safe to let informations such as

       <EncryptedKey xmlns="http://www.w3.org/2001/04/xmlenc#">
          <EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
    

    in the .config ?

    Isn't it possible to decrypt it with those informations ? After the file is encrypted, can you confirm i can comment this line :

      EncryptAppSettings("appSettings", configuration);
    

    When i try to get the username value after the file is encrypted with this line :

    string userNameafterEncryption = configuration.AppSettings.Settings["username"].Value;
    

    i get the decrypted value even if my file is now encrypted. I don't understand why...

    Thank you for your help

  • Tim
    Tim almost 4 years
    How do things happen when the application is published to a LAN server using ClickOnce with this setting: ...this application is available only online ?
  • Evk
    Evk almost 4 years
    @Tim I'm not sure, but there is a note in clickonce documentation, in section "Start the application from the Web or a network share": "Technically, the application is downloaded and installed to an application cache on the local computer". So since it runs from local folder as usual, I'd expect it to behave the same as described in answer.