Поделиться через


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

  • Anonymous
    January 01, 2017
    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.
  • Anonymous
    September 28, 2017
    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?
  • Anonymous
    February 06, 2018
    The comment has been removed
    • Anonymous
      February 14, 2018
      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
    • Anonymous
      March 13, 2018
      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 Paulfull 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; }}