Encryption using Azure Key Vault – C# and PowerShell


In this post I am going to show how you can encrypt strings using Azure Key Vault. Please refer this documentation for the encryption standards followed by Azure Key Vault. So, lets start by creating a new Key Vault in Azure. Once you have done that, generate a new Key which is a Software Key and name it as "NewKey".

The below C# class code will then be able to encrypt and decrypt strings using the Azure Key Vault. It uses Service Principal to access the key vault, so make sure your vault is accessible by the Service Principal you use to authenticate.

public class KeyVaultDecryptor
    {
        private string vaultAddress;
        private string clientId;
        private string clientSecret;
 
        public KeyVaultDecryptor(string vaultAddress, string clientId, string clientSecret)
        {
            this.vaultAddress = vaultAddress;
            this.clientId = clientId;
            this.clientSecret = clientSecret;
        }
        public string DecryptText(string textToDecrypt)
        {
            var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));
            try
            {
                var key = kv.GetKeyAsync(vaultAddress, "NewKey"null).GetAwaiter().GetResult();
                
                var publicKey = Convert.ToBase64String(key.Key.N);
                using (var rsa = new RSACryptoServiceProvider())
                {
                    var p = new RSAParameters() { Modulus = key.Key.N, Exponent = key.Key.E };
                    rsa.ImportParameters(p);
 
                    // Decrypt
                    var encryptedTextNew = Convert.FromBase64String(textToDecrypt);
                    var decryptedData = kv.DecryptDataAsync(key.Key, JsonWebKeyEncryptionAlgorithm.RSAOAEP, encryptedTextNew).GetAwaiter().GetResult();
                    var decryptedText = Encoding.Unicode.GetString(decryptedData.Result);
 
                    return decryptedText;
                }
            }
            catch (Exception ex)
            {
                return "";
            }
        }
 
        public string EncryptText(string textToEncrypt)
        {
            var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));
            try
            {
                var key = kv.GetKeyAsync(vaultAddress, "NewKey"null).GetAwaiter().GetResult();
                
                var publicKey = Convert.ToBase64String(key.Key.N);
                using (var rsa = new RSACryptoServiceProvider())
                {
                    var p = new RSAParameters() { Modulus = key.Key.N, Exponent = key.Key.E };
                    rsa.ImportParameters(p);
                    var byteData = Encoding.Unicode.GetBytes(textToEncrypt);
 
                    // Encrypt
                    var encryptedText = rsa.Encrypt(byteData, true);
                    string encText = Convert.ToBase64String(encryptedText);
                    return encText;
                }
            }
            catch (Exception ex)
            {
                return "";
            }
        }
 
        async Task<string> GetToken(string authorization, string resource, string scope)
        {
            var authContext = new AuthenticationContext(authorization);
                     ClientCredential clientCred = new ClientCredential(clientId,clientSecret);
            AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);
 
            if (result == null)
                throw new InvalidOperationException("Failed to obtain the JWT token");
 
            return result.AccessToken;
        }
    }

You can refer to my other blog here to convert this C# code to PowerShell or use the attached zipped module directly in PowerShell or Azure Automation - keyvaultdecryptor

A sample PowerShell code to use Key Vault Encryption in Azure Automation:

[System.Reflection.Assembly]::LoadFrom("C:\Modules\User\KeyVaultDecryptor\KeyVaultDecryptor.dll") | Out-Null ##For Azure Automation that is the path where modules get uploaded

$VaultAddress="https://****.vault.azure.net"

$ClientId="99b*****************1cb91d"

$ClientSecret="Cjl*****************yfTJes0U="

$KeyVaultClient = New-Object KeyVaultDecryptor.KeyVaultDecryptor -argumentlist $VaultAddress, $ClientId, $ClientSecret

$encrypt = $KeyVaultClient.EncryptText("Administrator@123")

$decrypt = $KeyVaultClient.DecryptText($encrypt)

Comments (5)

  1. appvn apk says:

    Thanks for sharing this valuable information to our vision. You have posted a trust worthy blog keep sharing. Nice article i was really impressed by seeing this article, it was very interesting and it is very useful for me.

  2. Patrick Knoles says:

    I have been able to use this in powershell for string encryption. Great! Thank you. Do you have any insight as to how to do the same with Azure CLI 2.0?

  3. Ricardo Ponce says:

    Great Post,
    I’m trying to use the C# class you created, but I’m having an issue on this line:

    var decryptedData = kv.DecryptDataAsync(key.Key, JsonWebKeyEncryptionAlgorithm.RSAOAEP, encryptedTextNew).GetAwaiter().GetResult();
    the error is:
    ‘Microsoft.Azure.KeyVault.KeyVaultClient’ does not contain a definition for ‘DecryptDataAsync’ and no extension method ‘DecryptDataAsync’ accepting a first argument of type ‘Microsoft.Azure.KeyVault.KeyVaultClient’ could be found (are you missing a using directive or an assembly reference?)

    I’m using .Net Framework 4.6 and seems that KeyVaultClient class does not has the DecryptDataAsync method, but the class KeyVaultClientExtensions has a DecryptAsync method instead has a DecryptDataAsync method, what do I need to make this code work?

    Best Regards,
    Ricardo

    1. Rohit Minni says:

      I am using Microsoft.Azure.KeyVault.dll – You can get the dll from the link in the post which is just below the C# code snippet

    2. Paul Mooij says:

      Hi Ricardo,
      I had the same issue, this is caused by the Microsoft.Azure.KeyVault.dll version via NuGet is 2.3.2 where Rohit used 1.0.0.

      I’ve adapted the class to use KeyName and the required KeyVersion and use the renamed DecryptAsync() method over DecryptDataAsync()
      works like a charm now!

      KR Paul

      full class specs:

      public class KeyVaultDecryptor
      {
      private string vaultAddress;
      private string clientId;
      private string clientSecret;
      private string keyName;
      private string keyVersion;

      public KeyVaultDecryptor(string vaultAddress, string clientId, string clientSecret, string keyName, string keyVersion)
      {
      this.vaultAddress = vaultAddress;
      this.clientId = clientId;
      this.clientSecret = clientSecret;
      this.keyName = keyName;
      this.keyVersion = keyVersion;
      }
      public string DecryptText(string textToDecrypt)
      {
      var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));
      try
      {
      var key = kv.GetKeyAsync(vaultAddress, keyName, keyVersion).GetAwaiter().GetResult();

      var publicKey = Convert.ToBase64String(key.Key.N);
      using (var rsa = new RSACryptoServiceProvider())
      {
      var p = new RSAParameters() { Modulus = key.Key.N, Exponent = key.Key.E };
      rsa.ImportParameters(p);

      // Decrypt
      var encryptedTextNew = Convert.FromBase64String(textToDecrypt);
      var decryptedData = kv.DecryptAsync(key.Key.Kid, JsonWebKeyEncryptionAlgorithm.RSAOAEP, encryptedTextNew).GetAwaiter().GetResult();
      var decryptedText = Encoding.Unicode.GetString(decryptedData.Result);

      return decryptedText;
      }
      }
      catch (Exception ex)
      {
      return “”;
      }
      }

      public string EncryptText(string textToEncrypt)
      {
      var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(GetToken));
      try
      {
      var key = kv.GetKeyAsync(vaultAddress, keyName, keyVersion).GetAwaiter().GetResult();

      var publicKey = Convert.ToBase64String(key.Key.N);
      using (var rsa = new RSACryptoServiceProvider())
      {
      var p = new RSAParameters() { Modulus = key.Key.N, Exponent = key.Key.E };
      rsa.ImportParameters(p);
      var byteData = Encoding.Unicode.GetBytes(textToEncrypt);

      // Encrypt
      var encryptedText = rsa.Encrypt(byteData, true);
      string encText = Convert.ToBase64String(encryptedText);
      return encText;
      }
      }
      catch (Exception ex)
      {
      return “”;
      }
      }

      async Task GetToken(string authorization, string resource, string scope)
      {
      var authContext = new AuthenticationContext(authorization);
      ClientCredential clientCred = new ClientCredential(clientId, clientSecret);
      AuthenticationResult result = await authContext.AcquireTokenAsync(resource, clientCred);

      if (result == null)
      throw new InvalidOperationException(“Failed to obtain the JWT token”);

      return result.AccessToken;
      }
      }

Skip to main content