GUITACA BLOGS
Blogs from our authors

Office 365: The best recipes for developers
Gustavo Velez
Learn more and buy
Return to Blogs
Maintaining secrets as JSON filesGustavo Velez
Secrets management is an important security issue when developing software. A simple and straightforward way to do it is by using encrypted JSON files13-10-2020
SharePoint

When developing new applications, it is very often necessary to maintain sensitive configuration data securely, as, for example, for login account names and passwords, connection strings for databases, etc. This is also a recurrent task when programming SharePoint, Outlook, Word, Excel, or PowerPoint AddIns, and when working with Azure Functions. There are several platforms to maintain that sort of data: The Azure Key Vault is a good example. But that kind of (sometimes expensive) infrastructure is not always really required.

The SecureStore is an Open Source solution for secrets management published by Mahmoud Al-Qudsi in GitHub (https://github.com/neosmart/SecureStore) and available with an MIT license. Currently, the library can be used in CSharp (.NET and Core Frameworks) and Rust projects, and it also contains a small Command-line tool to manage the secrets. The encryption is "defined as AES-128-CBC after out-of-band HMAC-SHA1 authentication, using two separate keys derived via 256,000 rounds of PBKDF2". More background information can be found in the site https://neosmart.net/blog/2020/securestore-open-secrets-format/.

The idea is to create a JSON file that contains a dictionary of KeyName-KeyValue, where the KeyValue is encrypted. The JSON file must be saved somewhere it is accessible for the rest of the solution, and the values are decrypted on-the-fly. The encryption uses a password that can be defined by the owner of the file, or autogenerated, and that can be also saved as a file.

Using the Command-line application

To make available the Command-line application (one-time action), open PowerShell and run the command:

   dotnet tool install --global SecureStore.Client

Full instructions can be found in the site https://github.com/neosmart/SecureStore/tree/master/Client.

To create a file with the key and a file with an empty (no key values) secrets store JSON file, use the next command. The application will stop to ask for the password:

   SecureStore create "C:\Temporary\mySecrets01.json" --keyfile "C:\Temporary\mySecrets01.key" --password

To add key values to the secrets repository file, use the command:

   SecureStore --store "C:\Temporary\mySecrets01.json" set "mySecret01" "mySecretValue01"

To retrieve the values of a key, use the command:

   SecureStore --store "C:\Temporary\mySecrets01.json" get "mySecret01"

And to retrieve all the values in the store, use the command:

   SecureStore --store "C:\Temporary\mySecrets01.json" get --all

There are also commands to delete keys from the repository.

The JSON file can be open with any ASCII text editor (the KeyName is not encrypted):

Using CSharp

To use the SecureStore library, first install the SecureStore NuGet in the Visual Studio Solution:

Then add a directive to "using NeoSmart.SecureStore;" in the source code file.

The key store can be created and maintained using a routine like the next one. Note that the password can be autogenerated, saved in an encrypted file, or directly using the password, as in the example:

static void CreateSecret()
{
	using (SecretsManager mySecretsMan = SecretsManager.CreateStore())
	{
		// mySecretsMan.GenerateKey();  // Auto-generated key
		// mySecretsMan.LoadKeyFromFile(@"C:\Temporary\mySecretKeyFile.key"); // Key from a file
		mySecretsMan.LoadKeyFromPassword("mySecurePassword"); // Key from a password
		mySecretsMan.ExportKey(@"C:\Temporary\mySecretsKeyFile.key"); // Save the key if necessary

		mySecretsMan.Set("myKey01", "Somebody Was Here"); // Create secret(s)
		mySecretsMan.Set("myKey02", "This is a value");

		mySecretsMan.SaveStore(@"C:\Temporary\mySecrets.bin"); // Save the store
	}
}

To retrieve one secret using a file with the password, use a routine as the next one:

static void RetrieveOneSecret()
{
	using (SecretsManager mySecretsMan = SecretsManager.LoadStore(@"C:\Temporary\mySecrets.bin"))
	{
		mySecretsMan.LoadKeyFromFile(@"C:\Temporary\mySecretsKeyFile.key"); // Key from file

		string mySecret = mySecretsMan.Get("myKey01");  // Get a secret

        if (!mySecretsMan.TryGetValue("myKey03", out string answer)) // Check for a key
        {
            Console.WriteLine("Secret of 'myKey03' not found");
        }
    }
}

And to retrieve all the keys in the store using the password directly, not a password file, the next routine can help:

static void RetrieveAllSecrets()
{
	using (SecretsManager mySecretsMan = SecretsManager.LoadStore(@"C:\Temporary\mySecrets.bin"))
	{
		mySecretsMan.LoadKeyFromPassword("mySecurePassword");  // Key from password

		foreach (string oneKey in mySecretsMan.Keys) // Get all secrets
		{
			Console.WriteLine(oneKey + " - " + mySecretsMan.Get(oneKey));
		}
	}
}

Return to Blogs