Failed to decrypt using provider 'DataProtectionConfigurationProvider' in app.config

8

I used following method to encrypt connectionstrings section of my app.config in my WinForms project(I'm using Code First EF in my project):

public static void EncryptConfig(string exeConfigName)
{
    var config = ConfigurationManager.OpenExeConfiguration(exeConfigName);
    var section = config.GetSection("connectionStrings") as ConnectionStringsSection;
    if (section != null || !section.SectionInformation.IsProtected)
    {
       section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
       config.Save();
    }
}

and I use following method to decrypt the connectionstrings section, too:

public static void DecryptConfig(string exeConfigName)
{
    var config = ConfigurationManager.OpenExeConfiguration(exeConfigName);
    var section = config.GetSection("connectionStrings") as ConnectionStringsSection;
    if (section != null && section.SectionInformation.IsProtected)
        section.SectionInformation.UnprotectSection();
}

this method works in my machine, but when I deploy my application to another machine I get following exception:

System.Configuration.ConfigurationErrorsException: Failed to decrypt using provider 'DataProtectionConfigurationProvider'. Error message from the provider: Key not valid for use in specified state. (Exception from HRESULT: 0x8009000B) (D:\l4test\Level4UI.exe.config line 82) ---> System.Runtime.InteropServices.COMException: Key not valid for use in specified state. (Exception from HRESULT: 0x8009000B)

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)

at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)

at System.Configuration.DpapiProtectedConfigurationProvider.DecryptText(String encText)

at System.Configuration.DpapiProtectedConfigurationProvider.Decrypt(XmlNode encryptedNode)

at System.Configuration.ProtectedConfigurationSection.DecryptSection(String encryptedXml, ProtectedConfigurationProvider provider)

at System.Configuration.Internal.InternalConfigHost.System.Configuration.Internal.IInternalConfigHost.DecryptSection(String encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)

at System.Configuration.Internal.DelegatingConfigHost.DecryptSection(String encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)

at System.Configuration.Internal.DelegatingConfigHost.DecryptSection(String encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfigSection)

at System.Configuration.BaseConfigurationRecord.CallHostDecryptSection(String encryptedXml, ProtectedConfigurationProvider protectionProvider, ProtectedConfigurationSection protectedConfig)

at System.Configuration.BaseConfigurationRecord.DecryptConfigSection(ConfigXmlReader reader, ProtectedConfigurationProvider protectionProvider)

--- End of inner exception stack trace ---

at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult)

at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)

at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)

at System.Configuration.Configuration.GetSection(String sectionName)

at IASCo.Infrastructure.Common.Utilities.Configuration.ConfigurationEncryption.DecryptConfig(string exeConfigName)

In this thread, Jeremy said:

You need to publish with the section decrypted. The key that is used to encrypt/decrypt is machine specific.

My app will be installed on a network share and run from there but there will be more than one person who may access the app from their work stations, How can I specify a single key to decrypt the connectionString section that will work from all the machines used to access the app.

I'm looking for a way to do this job(encrypt in my machine and decrypt in user's machines) using c#.

c#
winforms
entity-framework
encryption
app-config
asked on Stack Overflow Sep 21, 2016 by Masoud • edited Jun 20, 2020 by Community

1 Answer

1

Your code looks fine to me - other than needing to change from the user of

 if (section != null || !section.SectionInformation.IsProtected)
{
   section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
   config.Save();
}

to

 if (section != null || !section.SectionInformation.IsProtected)
    {
       section.SectionInformation.ProtectSection("RsaProtectionConfigurationProvider");
       config.Save();
    }

When you do create the RSA keys make sure you use the -exp switch to enable exporting of the keys as per the docs: https://msdn.microsoft.com/en-us/library/yxw286t2.aspx

aspnet_regiis -pc "KeysetName"–exp

As stated by the earlier answerers. In addition to this, if the users of the application are on an IIS network, you may user ASP.NET Impersonation vis your organisations access control lists (ACLs). This will allow you to remove the need to authenticate on a machine level, which doesn't suit all applications. See: https://msdn.microsoft.com/en-us/library/xh507fc5.aspx

answered on Stack Overflow Oct 1, 2016 by Jordan Green

User contributions licensed under CC BY-SA 3.0