Securing applications is hard. We often have to struggle with storing connection strings, encryption keys and other sensitive pieces of information securely in our code base. Azure Key Vault is a great place to store these securely and allow only limited access to authorized applications. Azure Key Vault can store Keys, Secrets and Certificates. It supports storing only asymmetric keys (RSA and EC). One can generate a key in Azure Key Vault and it will only give out Public Key to your application. All operations involving Private Key has to be done by Azure Key Vault only. Encryption algorithms like AES are symmetric encryption methods - meaning they use one key to encrypt and decrypt the data. There are two ways we can store this key - either as a secret in Azure Key Vault (less secure) or encrypt the key itself using the RSA key generated in Azure Key Vault and store the encrypted key as a secret (more secure). If you are using .NET, there are numerous examples on the interwebs showing how to do this using the old Microsoft.Azure.KeyVault libraries. (Un)Fortunately those libraries are now replaced by new Azure SDKs splitting the one library in three separate Nuget packages:
How do we encrypt/decrypt using these packages? Sadly the documentation regarding these is sparse. Hence this blog post.
In the following code, we create a small console application using .NET Core and pull down a RSA key generated in Azure Key Vault named "KEK" (Key Encryption Key). We use that key to encrypt the string passed in by the user and store in Azure Key Vault as a secret. Finally to get back the original string, we pull down the secret stored in previous step and use the KEK to decrypt the string back to original value.
using System;
using System.Text;
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Security.KeyVault.Secrets;
namespace key_vault_console_app
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter string to encrypt:");
var keyToEncrypt = Console.ReadLine();
Console.WriteLine("Encrypting...");
var credential = new ClientSecretCredential("AzureTenantId", "ClientId", "ClientSecret");
var kvUri = "https://YourKeyVaultName.vault.azure.net";
var client = new KeyClient(new Uri(kvUri), credential);
var key = client.GetKey("KEK");
var cryptoClient = new CryptographyClient(key.Value.Id, credential);
EncryptResult encryptResult = cryptoClient.Encrypt(EncryptionAlgorithm.RsaOaep256, Encoding.UTF8.GetBytes(keyToEncrypt));
Console.WriteLine("Encrypted string is: " + Convert.ToBase64String(encryptResult.Ciphertext));
// Store the encrypted key in Azure KV as secret
var secretClient = new SecretClient(new Uri(kvUri), credential);
secretClient.SetSecret(new KeyVaultSecret("EncryptedKey1", Convert.ToBase64String(encryptResult.Ciphertext)));
Console.WriteLine("Do you want to decrypt? (Y/N)");
if (Console.ReadLine().ToUpper() == "Y")
{
var encryptedSecret = secretClient.GetSecret("EncryptedKey1");
DecryptResult decryptResult = cryptoClient.Decrypt(EncryptionAlgorithm.RsaOaep256, Convert.FromBase64String(encryptedSecret.Value.Value));
Console.WriteLine("Decrypted string is: " + Encoding.UTF8.GetString(decryptResult.Plaintext));
}
Console.ReadLine();
}
}
}
Hope the above example helps someone struggling with using the new Azure SDKs. Is there a better way to do this? Do let me know in the comments below.
Comments
Post a Comment
As far as possible, please refrain from posting Anonymous comments. I would really love to know who is interested in my blog! Also check out the FAQs section for the comment policy followed on this site.