How to encrypt / decrypt a configuration file section with RsaProtectedConfigurationProvider
Asked Answered
F

3

6

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

Facelift answered 10/5, 2016 at 14:53 Comment(0)
N
22

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.

Numismatics answered 12/5, 2016 at 18:1 Comment(2)
How do things happen when the application is published to a LAN server using ClickOnce with this setting: ...this application is available only online ?Tournai
@Tournai 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.Numismatics
O
0

https://learn.microsoft.com/en-us/previous-versions/aspnet/yxw286t2(v=vs.100)


Create a RSA Key Container

aspnet_regiis -pc "MyKeys" –exp

Add file config configProtectedData keyContainerName="MyKeys"


Assign permissions to the RSA key container:

aspnet_regiis -pa "MyKeys" "iis apppool\SCI"  
aspnet_regiis.exe -pef "connectionStrings" H:\inetpub\wwwroot\SCI\SCICampanas -prov "MyProvider"
aspnet_regiis.exe -pdf "connectionStrings" H:\inetpub\wwwroot\SCI\SCICampanas

Edit file config and remove configProtectedData

Obese answered 9/11, 2022 at 23:36 Comment(0)
F
0

You can place this file in the application directory as decrypt.aspx. Invoke the file locally as: http://127.0.0.1/my-site/decrypt.aspx

<%@ Page Language="VB" %>
<%@ Import Namespace="System.Configuration" %>
<%@ Import Namespace="System.Web.Configuration" %>
<%@ Import Namespace="System.Data" %>
<script runat="server">

Public Sub Page_Load()

    ConnectionStringsGrid.DataSource = ConfigurationManager.ConnectionStrings
    ConnectionStringsGrid.DataBind()

    Dim collection = ConfigurationManager.AppSettings
    Dim table As New DataTable()

    table.Columns.Add("Key")
    table.Columns.Add("Value")

    For Each item in collection
        table.Rows.Add(item,collection(item))
    Next

    Dim view As New DataView(table)
    AppSettingsGrid.DataSource = view
    AppSettingsGrid.DataBind()

  
    Dim config As System.Configuration.Configuration = _
        WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath)
    Dim key As MachineKeySection = _
        CType(config.GetSection("system.web/machineKey"), MachineKeySection)
    DecryptionKey.Text = key.DecryptionKey
    ValidationKey.Text = key.ValidationKey
    IP.Text =  Request.UserHostAddress

    If IP.Text <> "127.0.0.1" then
        Response.Clear()
        Response.StatusCode = 404
        Response.End()
        HttpContext.Current.ApplicationInstance.CompleteRequest()
    End If
    
End Sub

</script>
<html>

<body>

<form runat="server">

  <asp:GridView runat="server" CellPadding="4" id="ConnectionStringsGrid" />
  <P>
  <asp:GridView runat="server" CellPadding="4" id="AppSettingsGrid" />
  <P>  
  MachineKey.IP = <asp:Label runat="Server" id="IP" /><BR>  
  MachineKey.DecryptionKey = <asp:Label runat="Server" id="DecryptionKey" /><BR>
  MachineKey.ValidationKey = <asp:Label runat="Server" id="ValidationKey" />

</form>

</body>
</html>
Flowerlike answered 7/7, 2023 at 16:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.