4

I created a new .NET Core 2.1 Console project. I added Config.xml:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
      <add name="MyLocalSQLServer" connectionString="Initial Catalog=aspnetdb;data source=localhost;Integrated Security=SSPI;" providerName="System.Data.SqlClient"/>
  </connectionStrings>
</configuration>

In Program.cs:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(ConfigurationManager.ConnectionStrings["MyLocalSQLServer"]);            
    }
}

With aspnet_regiis, I encrypted the configuration file:

RENAME "C:\repos\ConsoleApp7\bin\Debug\netcoreapp2.1\ConsoleApp.dll.config" web.config
aspnet_regiis -pef "connectionStrings" "C:\repos\ConsoleApp\bin\Debug\netcoreapp2.1"
RENAME "C:\repos\ConsoleApp7\bin\Debug\netcoreapp2.1\web.config" ConsoleApp.dll.config

Finally, I ran the app:

dotnet "C:\repos\ConsoleApp7\bin\Debug\netcoreapp2.1\ConsoleApp.dll"

I got the error:

Unhandled Exception: System.Configuration.ConfigurationErrorsException: 
 Failed to decrypt using provider 'RsaProtectedConfigurationProvider'. 
 Error message from the provider: Operation is not supported on this platform. 
 ---> System.PlatformNotSupportedException: Operation is not supported on this platform.
   at System.Configuration.RsaProtectedConfigurationProvider.Decrypt(XmlNode encryptedNode)
   at System.Configuration.ProtectedConfigurationSection.DecryptSection(String encryptedXml, ProtectedConfigurationProvider provider)
   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.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, 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.BaseConfigurationRecord.GetSection(String configKey)
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.get_ConnectionStrings()
   at ConsoleApp7.Program.Main(String[] args)

This trick works to encrypt app.config with the old .NET Framework, but it isn't supported by .NET Core.

The purpose of this is to test migration from .NET Framework to .NET Core.

How can I encrypt app.config in .NET Core?

Wyck
  • 10,311
  • 6
  • 39
  • 60
vernou
  • 6,818
  • 5
  • 30
  • 58
  • I can't correct the title. If somebody can, it will be pleasant. – vernou Aug 27 '19 at 15:32
  • any reason for that in particular, though? Encrypting it will make it harder to modify in production, but it won't make it harder for an attacker to decrypt it. By the way, are you using IIS or IIS Express/Kestrel? – Lucca Ferri Aug 27 '19 at 15:32
  • and I have removed the pad in the title, it is in queue to be peer reviewed. – Lucca Ferri Aug 27 '19 at 15:34
  • Thank. It's principally to aps.net core API Rest, but also few batch console. – vernou Aug 27 '19 at 15:37
  • I know how it's used, I just don't understand why it's needed. It doesn't add much protection at all, especially if someone dumps the memory of the running process, and it would give you problems to modify later in production. But if you really need to do this, I'd create another file instead, or a section in the app.config with the encrypted string. – Lucca Ferri Aug 27 '19 at 15:39
  • I don't need a perfect protection. But all secrets are visible in a file. It's limit. aspnet_regiis has a good rate time/protection, but It don't work with .NET Core. – vernou Aug 27 '19 at 15:46
  • What platform are you on? – spodger Aug 27 '19 at 16:31
  • Looks like this api is not supported in .net core https://github.com/dotnet/corefx/issues/14950 https://github.com/dotnet/corefx/blob/master/src/System.Configuration.ConfigurationManager/src/System/Configuration/RsaProtectedConfigurationProvider.cs#L19 – TylerReid Aug 27 '19 at 16:40
  • @spodget, Windows Server 2016. – vernou Aug 28 '19 at 13:10
  • There are several [alternatives](https://stackoverflow.com/questions/36062670/encrypted-configuration-in-asp-net-core) for ASP.NET Core, in case that's an option. – user7217806 Aug 31 '19 at 20:10

2 Answers2

3

As "Off The Gold" answered, RsaProtectedConfigurationProvider is not supported by .NET Core and .NET 5+

However I got it working in .NET 7.0 using DataProtectionConfigurationProvider (DPAPI)

here's a working encrypt.bat file:

set mypath=%cd%
rename "app.config" "web.config"

cd "C:\Windows\Microsoft.NET\Framework64\v4.0.30319"
aspnet_regiis.exe -pef "appSettings" "%mypath%" -prov "DataProtectionConfigurationProvider"
aspnet_regiis.exe -pef "connectionStrings" "%mypath%" -prov "DataProtectionConfigurationProvider"

cd "%mypath%" 
rename "web.config" "app.config" 

pause
2

Unfortunately you can't per the article: https://learn.microsoft.com/en-us/dotnet/api/system.configuration.rsaprotectedconfigurationprovider?view=dotnet-plat-ext-7.0#remarks

Where it states:

On .NET Core and .NET 5+, the RsaProtectedConfigurationProvider type is not supported. All APIs throw a PlatformNotSupportedException at run time.

Off The Gold
  • 1,228
  • 15
  • 28