The DevAttic ConfigCrypter makes it easy for you to encrypt and decrypt config files. It consists of two parts. A command line utility that lets you encrypt keys in your JSON configuration files and a library that decrypts them on the fly in your .NET Standard applications.
Encrypted configuration files will not make your server infrastructure unhackable. Usually the certificate to decrypt is hosted on the same server as your web application. This means an attacker could decrypt your config if your server is not secure and the attacker gains access.
Additional security could be achieved by:
- Storing your certificate in the windows certificate store (supported by ConfigCrypter) and restricting access to it.
- Protect your certificate with a password that is embedded in your source code (currently not supported, but could be easily implemented).
- Don't storing your certificate in any where, ConfigCrypter now supports symmetric encrypt and RAS raw data, you can enter your key in the console or a web page(via https) to initialize ConfigCrypter when your app startup.
Also these methods would not be perfectly safe. In fact it only makes things harder for an attacker.
Other possibilities would be using Environment variables or the Secret Manager tool, but in these variants the settings are completely unencrypted. For production scenarios Microsoft recommends using the Azure Key Vault, but also this is not perfectly safe and forces you to use Azure.
It is definitely required to secure your server infrastructure, as this is the only way to protect your connection strings and other sensitive configuration values.
- Lets you encrypt only certain keys in your config, so the rest of the config is still readable.
- Access the encrypted values the same way you are used to in your .NET Core applications.
- Lets you share config files or even check them in in your VCS without the need to remove sensitive information.
To use DevAttic ConfigCrypter you will first need to create a self signed X509 certificate that is being used for the encryption and decryption. An easy way to do this is being described in this guide: Link
In fact you can follow every guide as long as the result is a certificate in .pfx format containing a public and private key.
If you now have your certificate you need to decide what keys you want to encrypt. Lets assume we have a JSON file that looks like this:
{
"Nested": {
"KeyToEncrypt": "This will be encrypted"
}
}
We want to encrypt the value with the key Nested.KeyToEncrypt
. Notice the separation of the keys with a dot. How the
key is interprated and what kind of syntax is used to define your key is up to the IConfigCrypter implementation.
Currently only JSON is supported and the JsonConfigCrypter
is using the JSONPath Syntax to define your
keys (Link). Altough JSONPath usually needs a $ to define the root of the
object you can leave it out here.
To install the crypter command line utility just
execute dotnet tool install -g DevAttic.ConfigCrypter.Console
. After that you can use it with the
command config-crypter
from your command line. Note: these feature are not supported by this tool command: symmetric encryption, changing encryption key, key-prefix and --keys option, encrypt/decrypt entire config file.
To encrypt our key from above we simple execute:
config-crypter encrypt -p c:\path\to\cert.pfx -f c:\path\to\config.json -k "Nested.KeyToEncrypt"
.
After that a new files named config_encrypted.json
should be created at the same folder as your original config file.
This file is now the same as the original one except for the fact that the value for the passed key has been encrypted.
If you want to prevent the creation of a new file you can simply pass --replace (-r) as additional paramter to the command and the original file will be replaced.
To decrypt the file again you can simply execute:
config-crypter decrypt -p c:\path\to\cert.pfx -f c:\path\to\config_encrypted.json -k "Nested.KeyToEncrypt"
To encrypt our keys for the entire file use symmetric encryption we simple execute DevAttic.ConfigCrypter.Console
project with arguments:
encrypt -f <path-to-the-file> --secret-key 123456 --secret-iv 123 --key-prefix <the-key-should-be-encrypted> -l <the-key-should-be-encrypted>
and the encrypted file will be created in same directory as same filename with _encrypted
postfix. the --secret-iv
option is optional, --secret-iv
is generated by default when unspecific.
To decrypt our keys for the entire file use symmetric encryption we simple execute DevAttic.ConfigCrypter.Console
project with arguments:
decrypt -f <path-to-the-file> --secret-key 123456 --secret-iv 123 --key-prefix <the-key-should-be-encrypted> -l <the-key-should-be-encrypted>
and the decrypted file will be created in same directory as same filename with _decrypted
postfix. the --secret-iv
option is optional, the decryption will be ok when the --secret-iv
is generated.
To change the secret key/iv of the encrypted config file, we simple execute DevAttic.ConfigCrypter.Console project with arguments:
change -f <path-to-the-encrypted-config-file> --secret-key <old-secret-key> --secret-iv <old-iv-if-required> --secret-key-new <new-srcret-key-to-change> --key-prefix <the-key-should-be-encrypted> -l <the-key-should-be-encrypted>
and the re-encrypted file will be created in same directory as same filename with _changed
postfix.
As above operations, you can copy your result files into your project to be used.
The following command line arguments can be passed for the encrypt and decrypt command.
-p, --path (Group: CertLocation) Path of the certificate.
--password Password of the certificate (if available).
-n, --name (Group: CertLocation) The subject name of the certificate (CN). This can only be used in Windows environments.
-k, --key (Group: theKeys) The key to encrypt in the config file.
-l, --keys (Group: theKeys) The keys to encrypt in the config file.
--key-prefix (Group: theKeys) The prefix of the value of the keys to encrypt in the config file.
-f, --file Required. The path to the config file.
-r, --replace (Default: false) Replaces the original file if passed as parameter.
--format (Default: Json) The format of the config file.
--help Display this help screen.
--version Display version information.
--secret-key (Group: CertLocation) Key for the symmetric encryption.
--secret-iv Iv for the symmetric encryption.
for changing the secret key or certificate of the encrypted config file.
--path-new (Group: CertLocationNew) Path of the new certificate.
--name-new (Group: CertLocationNew) The subject name of the new certificate (CN). This can only be used in Windows environments.
--password-new Password of the new certificate (if available).
--secret-key-new (Group: CertLocationNew) New key for the symmetric encryption.
--secret-iv-new New Iv for the symmetric encryption.
Install the nuget package DevAttic.ConfigCrypter
To use your encrypted configuration file in your .NET Core applications, DevAttic ConfigCrypter provides convenient extension methods to register the needed configuration providers.
There are two extension methods that can be used to integrate encrypted configuration files.
AddEncryptedAppSettings
: Adds a configuration provider that decrypts certain keys of the appsettings.json file.AddEncryptedJsonConfig
: Adds a configuration provider that decrypts certain keys of a given JSON configuration file.
If you encrypted a key in the appsettings.json file of your ASP.NET Core web application you can use the following to enable the decryption.
The easiest way to enable decryption is to modify the CreateHostBuilder
function in your Program.cs
file.
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration(cfg =>
{
cfg.AddEncryptedAppSettings(crypter =>
{
crypter.Type = CryptType.Asymmetric;
crypter.CertificatePath = "cert.pfx";
crypter.KeysToDecrypt = new List<string> { "Nested:KeyToEncrypt" };
});
});
As you can see enabling decryption is as simple as adding a line of code. You just need to specify the path to the certificate and the keys that should be decrypted.
If you want to also use the environment specific appsettings files (appsettings.Development.json, appsettings.Production.json) please use the overloaded method to configure as shown below:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration((hostingContext, cfg) =>
{
cfg.AddEncryptedAppSettings(hostingContext.HostingEnvironment, crypter =>
{
crypter.Type = CryptType.Asymmetric;
crypter.CertificatePath = "cert.pfx";
crypter.KeysToDecrypt = new List<string> { "Nested:KeyToEncrypt" };
});
});
Notice how to HostingEnvironment
property of the hostingContext
variable is used.
Notice that nested keys have to be separated with colons in this case, because this is the default way to access nested configuration properties in .NET Core (Link) .
Certificates can be generated by using Openssl. An example certificate is already in the project and the encrypted string in the example appsettings files has been encrypted with it. To generate a certificate you could use the following commands:
openssl genrsa 2048 > private.key
openssl req -new -x509 -nodes -sha1 -days 365 -key private.key > public.cer
openssl pkcs12 -export -in public.cer -inkey private.key -out cert.pfx
If there an error on MacOS when creating X509Certificate2, you need to add a password in your cert file, and use below commands to generate a certificate. first command will generate private key and pem cert, you need to enter the password of private key. second command will convert cert from pem to pfx, also you need to enter the password of private key and enter the new password of pfx certificate. see also at dotnet/runtime#18254 (comment) and dotnet/runtime#23635
openssl req -x509 -newkey rsa:4096 -keyout testkey.pem -out testcert.pem
openssl pkcs12 -export -out badfinal.pfx -inkey testkey.pem -in testcert.pem