Reputation: 3
I'm encrypting a string using Azure CLI:
az keyvault key encrypt --id "https://myhsmtest.managedhsm.azure.net/keys/aes256/1234aed127f8009e15d6c3a883b91f21" --algorithm A256GCM --value "123" --data-type plaintext
This returns me a JSON:
{
"aad": null,
"algorithm": "A256GCM",
"iv": "8f7f424c8548bac26c947bfd",
"kid": "https://myhsmtest.managedhsm.azure.net/keys/aes256/1234aed127f8009e15d6c3a883b91f21",
"result": "PtLm",
"tag": "e96de8eee3e194529095ef196f54cef0"
}
Now I'd like to decrypt this in C#:
var json =
"{\n \"aad\": null,\n \"algorithm\": \"A256GCM\",\n \"iv\": \"8f7f424c8548bac26c947bfd\",\n \"kid\": \"https://myhsmtest.managedhsm.azure.net/keys/aes256/1234aed127f8009e15d6c3a883b91f21\",\n \"result\": \"PtLm\",\n \"tag\": \"e96de8eee3e194529095ef196f54cef0\"\n}";
var jsonDocument = JsonDocument.Parse(json);
var cipherText = jsonDocument.RootElement.GetProperty("result").GetString();
var iv = jsonDocument.RootElement.GetProperty("iv").GetString();
var tag = jsonDocument.RootElement.GetProperty("tag").GetString();
var cipherTextBytes = Convert.FromBase64String(cipherText);
var ivBytes = Convert.FromBase64String(iv);
var tagBytes = Convert.FromBase64String(tag);
var keyVaultUrl = "https://myhsmtest.managedhsm.azure.net";
var credential = new DefaultAzureCredential();
var client = new KeyClient(vaultUri: new Uri(keyVaultUrl), credential);
var cryptographyClient = client.GetCryptographyClient("aes256", "1234aed127f8009e15d6c3a883b91f21");
DecryptParameters decryptParameters = DecryptParameters.A256GcmParameters(ciphertext: cipherTextBytes, iv: ivBytes, authenticationTag: tagBytes);
var result = cryptographyClient.Decrypt(decryptParameters);
It fails with the following error:
Azure.RequestFailedException: HSM Error: Invalid input data/params (Activity ID: e947a2ec-9f6d-11ef-846b-000d3a278b83)
Status: 400 (Bad Request)
ErrorCode: BadParameter
Content:
{"error":{"code":"BadParameter","message":"HSM Error: Invalid input data/params (Activity ID: e947a2ec-9f6d-11ef-846b-000d3a278b83)"}}
Headers:
x-ms-server-latency: REDACTED
Cache-Control: no-cache
X-Content-Type-Options: REDACTED
x-ms-request-id: e947a2ec-9f6d-11ef-846b-000d3a278b83
Strict-Transport-Security: REDACTED
Content-Security-Policy: REDACTED
X-Frame-Options: REDACTED
Content-Type: application/json; charset=utf-8
Content-Length: 134
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequest(Request request, CancellationToken cancellationToken)
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequest[TContent,TResult](RequestMethod method, TContent content, Func`1 resultFactory, CancellationToken cancellationToken, String[] path)
at Azure.Security.KeyVault.Keys.Cryptography.RemoteCryptographyClient.Decrypt(DecryptParameters parameters, CancellationToken cancellationToken)
at Azure.Security.KeyVault.Keys.Cryptography.RemoteCryptographyClient.Azure.Security.KeyVault.Keys.Cryptography.ICryptographyProvider.Decrypt(DecryptParameters parameters, CancellationToken cancellationToken)
at Azure.Security.KeyVault.Keys.Cryptography.CryptographyClient.Decrypt(DecryptParameters decryptParameters, CancellationToken cancellationToken)
...
If I encrypt a string in C# and decrypt it right away using EncryptResult.Ciphertext, EncryptResult.Iv and EncryptResult.AuthenticationTag, it works well. But when I'm using JSON from CLI in C# - I have this error.
If I use values from this JSON in CLI (az keyvault key decrypt), it also works well.
So I suppose that I'm not doing decoding of result, iv and tag from JSON to bytes[] well, but I don't get what is exactly wrong.
Upvotes: 0
Views: 92
Reputation: 10455
Azure Managed HSM: Decrypt in C# using encryption result from Azure CLI.
In my environment, I encrypted the azure Managed HSM key same as your Azure CLI command:
az keyvault key encrypt --id "https://xxx.managedhsm.azure.net/keys/Venkatesan326/xxxxxx" --algorithm A256GCM --value "this is plaintext" --data-type plaintext
This command is in preview and under development. Reference and support levels: https://aka.ms/CLI_refstatus
{
"aad": null,
"algorithm": "A256GCM",
"iv": "40f91e6934c5af97b6d18ec6",
"kid": "https://xxx.managedhsm.azure.net/keys/Venkatesan326/xxx",
"result": "xxxx=",
"tag": "ac077axxxxbd15af346"
}
I agree with Topaco's comment it should be in hexa encoded. you can use the below code which decrypt the encryption result from azure cli using C#.
Code:
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using Azure.Security.KeyVault.Keys.Cryptography;
using System;
using System.Text;
public class AzureHSMDecryptionExample
{
public static void Main(string[] args)
{
// Updated JSON response from Azure CLI (adjust values accordingly)
var json =
"{\n \"aad\": null,\n \"algorithm\": \"A256GCM\",\n \"iv\": \"4xxxxx\",\n \"kid\": \"https://xxxx.managedhsm.azure.net/keys/Venkatesan326/xxxx\",\n \"result\": \"xxxx\",\n \"tag\": \"xxxx\"\n}";
// Parse the JSON response
var jsonDocument = System.Text.Json.JsonDocument.Parse(json);
var cipherText = jsonDocument.RootElement.GetProperty("result").GetString();
var iv = jsonDocument.RootElement.GetProperty("iv").GetString();
var tag = jsonDocument.RootElement.GetProperty("tag").GetString();
byte[] ivBytes = HexStringToByteArray(iv);
byte[] tagBytes = HexStringToByteArray(tag);
byte[] cipherTextBytes = Convert.FromBase64String(cipherText);
// KeyVault URI and credentials
var keyVaultUrl = "https://xxx.managedhsm.azure.net";
var credential = new DefaultAzureCredential();
var client = new KeyClient(new Uri(keyVaultUrl), credential);
var cryptographyClient = client.GetCryptographyClient("Venkatesan326", "xxxx");
// Create the decrypt parameters using the A256GcmParameters method
var decryptParameters = DecryptParameters.A256GcmParameters(
ciphertext: cipherTextBytes,
iv: ivBytes,
authenticationTag: tagBytes
);
// Perform decryption
try
{
var result = cryptographyClient.Decrypt(decryptParameters);
string decryptedValue = Encoding.UTF8.GetString(result.Plaintext);
Console.WriteLine("Decrypted Value: " + decryptedValue);
}
catch (Exception ex)
{
Console.WriteLine($"Decryption failed: {ex.Message}");
}
}
public static byte[] HexStringToByteArray(string hex)
{
int length = hex.Length / 2;
byte[] bytes = new byte[length];
for (int i = 0; i < length; i++)
{
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return bytes;
}
}
Output:
Decrypted Value: this is plaintext
Upvotes: 0