joeschmoe54321
joeschmoe54321

Reputation: 93

How to properly store and access encrypted values in .NET 5.0 appsettings.json file?

I need to be able to store sensitive data in an appsettings.json config file for .NET 5.0 applications. I have been using RSA encryption of config files for .NET Framework apps, but I am moving to .NET 5.0 app development instead and I want a simpler way of storing/accessing secrets than the old reg_iis.exe approach.

I have tried one approach and gotten dangerously close to having it work, but perhaps there is a better way. My approach:

  1. Set encrypted values in my appsettings.json file. These ecrypted values are generated via the following PowerShell script, then copied to .json file:
$SecureString = Read-Host "Enter the String to Encrypt" -AsSecureString

$EncryptedString = ConvertFrom-SecureString -SecureString $SecureString

$EncryptedString
  1. An extension method in a .NET 5.0 app to decrypt the string:
public static string Decrypt(this string str)
{
    int length = str.Length / 2;
    byte[] encryptedData = new byte[length];
    for (int index = 0; index < length; ++index)
    {
        encryptedData[index] = byte.Parse(str.Substring(2 * index, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture);
    }

    // Decrypt the byte array to Unicode byte array
    byte[] data = ProtectedData.Unprotect(encryptedData, null, DataProtectionScope.CurrentUser);

    // Convert Unicode byte array to string
    return Encoding.Unicode.GetString(data);
}
  1. This extension method works if it is in the application, however I will need this for many applications. So I built it into a Class Library so I can just add a single .dll reference to each application. The problem is that it relies on the System.Security.Cryptography.ProtectedData class. This thing is apparently not supported out of the box with .NET 5.0, instead it is a Platform Extension that can be included via NuGet. I have done so, and as I said, it works if its in an application directly, but as part of the class library, it does not... If I include the class library assembly reference in an application, the class library builds fine, but there is an exception:

System.IO.FileNotFoundException: 'Could not load file or assembly 'System.Security.Cryptography.ProtectedData, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.'

It's not deploying the ProtectedData .dll to the consuming application, and I think it should be...

So, am I doing this inherently wrong, or am I close?

Upvotes: 1

Views: 1379

Answers (1)

Collin Dauphinee
Collin Dauphinee

Reputation: 13973

You're running into missing assembly errors because you're referencing the compiled library directly. The build system doesn't know about its dependencies (i.e. ProtectedData.dll), so it doesn't include them in your output folder when you build the application.

When you instead reference the library as a project, the build system can figure out everything that the library depends on by reading the project file, and include those dependencies in the output folder.

If you really need to reference the DLL directly for some reason, you need to copy its dependencies (generally the entire output folder from building it) into your application's directory.

It's much easier to just reference it as a project, unless there's some constraint preventing it. If it's not possible, deploying and referencing it as a NuGet package is an alternative that will ensure you automatically get all of the dependencies, but that comes with its own complexity.


On the topic of what you're trying to do with appsettings, this isn't going to work.

The methods you're calling pass through to the winapi CryptProtectData and CryptUnprotectData methods. They use a key derived from your login credentials, so it's not possible for data encrypted on one machine to be decrypted by another machine (or even another user on the same machine).

You can read up on alternative approaches for storing sensitive information here: https://learn.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-6.0&tabs=windows

Upvotes: 2

Related Questions