If you just want to keep it away from GIT, and don't require encryption, you can use the Secret Manager Tool as described. Then it is stored in a secrets.json
file within your user profile (but unencrypted). And as Microsoft describes it, it is limited to ASP.NET Core applications, which is not true - another StackOverflow Q&A shows you how to do it in a .NET core console application as well.
But if you need encryption, you can use the following methods of the .NET Framework; they use the DPAPI internally to protect (encrypt) your data, and you can directly use them in C# or VB.NET without having to fiddle around with system DLL calls:
namespace System.Security.Cryptography
{
// Summary:
// Provides methods for protecting and unprotecting data. This class cannot
// be inherited.
public sealed class ProtectedData
{
public static byte[] Protect(byte[] userData,
byte[] optionalEntropy, DataProtectionScope scope);
public static byte[] Unprotect(byte[] encryptedData,
byte[] optionalEntropy, DataProtectionScope scope);
}
}
To use it, add the reference System.Security
to your project. I strongly recommend using the byte array optionalEntropy
to add a SALT to your protected data (add some random values to the byte array which are unique for the data you intend to protect).
For scope
you can use DataProtectionScope.CurrentUser
, which will encrypt the data to protect with the current user's credentials.
In some scenarios, DataProtectionScope.LocalMachine
is useful, as well. In this case, the protected data is associated with the machine context. With this setting, any process running on the computer can unprotect data. It is usually used in server-specific applications that run on a server where untrusted users are not allowed access.
Use the Protect
method to encrypt the data, decrypt it with Unprotect
. You may store the returned byte array according to the requirements of your application (file, database, registry, etc).
If you have to protect a string, you can use a helper method such as:
byte[] GetBytes(string text) => System.Text.Encoding.Unicode.GetBytes(text);
to convert it to a byte array.
Vice versa, if you unprotect the byte array, you can get the string back vie:
string GetString(byte[] text) => System.Text.Encoding.Unicode.GetString(text);
If your string is not Unicode, you can find more encodings in the System.Text.Encoding
library of .NET.
Simple example (using the helper methods above together with the ProtectedData class):
using System.Security.Cryptography;
using static System.Security.Cryptography.ProtectedData;
void Main()
{
const DataProtectionScope scope = DataProtectionScope.CurrentUser;
byte[] salt = GetBytes("s5Dk9Fj2L12"); // change the salt
// protect msg
string msg = "Hello World!";
var protMsg = Protect(GetBytes(msg), salt, scope);
// get plaintext back
string plainTxt = GetString(Unprotect(protMsg, salt, scope));
Console.WriteLine(plainTxt);
}
More about the methods from DPAPI can be found here at MSDN:
For code samples and in case you are interested in encrypting parts of the application's .config file, check this out:
I recommend you to use a SALT (by using the optionalEntropy
parameter) - it protects against rainbow table attacks.
There is one drawback of the DPAPI solution I'd like to mention: the key is generated based on your Windows credentials, which means whoever has access to your Windows credentials possibly has access to the protected data (but note that the same is true if you're using BitLocker to encrypt your files). A program running under your account can access the protected data as well.
Finally one remark: You can combine the techniques described here (i.e. use the Secret Manager Tool and encrypt the settings stored in the secret.json
file - however then you require to store it in text format so you might need to encrypt and then encode it with Base64).