Ian
Ian

Reputation: 4457

How do you decrypt blobs with Azure KeyVault keys in Azure.Storage v12

Our code is currently using the old Microsoft.WindowsAzure.Storage libraries for blob storage access in Azure. I am trying to use the new v12 Azure.Storage.Blobs libraries to replace the old ones, however I cannot figure out how to decrypt/encrypt the blobs. The MS docs (https://learn.microsoft.com/en-us/azure/storage/blobs/storage-encrypt-decrypt-blobs-key-vault?tabs=dotnet) helpfully say that the v12 code snippets aren't ready yet, so there are no code examples.

The old code is like this:

var tokenProvider = new AzureServiceTokenProvider();
var cloudResolver = new KeyVaultKeyResolver(
    new KeyVaultClient.AuthenticationCallback(_tokenProvider.KeyVaultTokenCallback));
var encryptionThingy = await cloudResolver.ResolveKeyAsync(<Key Vault URL> + "/keys/" + <key name>, CancellationToken.None);
var policy = new BlobEncryptionPolicy(encryptionThingy, cloudResolver);
var options = new BlobRequestOptions() { EncryptionPolicy = policy };
await <ICloudBlob Instance>.DownloadToStreamAsync(<stream>, null, options, null);

So far with the new code I've gotten here:

var azureKeys = new KeyClient(new Uri(<key vault url>), new DefaultAzureCredential());
var encKey = azureKeys.GetKey(<key name>);
ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
{
    KeyEncryptionKey = (IKeyEncryptionKey)key
};
var bsClient = new BlobServiceClient(cStr, new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions });
var containerClient = new BlobContainerClient(cStr, containerName);
bClient = containerClient.GetBlobClient(<blob name>);

Of course this throws an exception because KeyVaultKey cannot be converted to IKeyEncryptionKey. So my questions are

  1. Can the key be converted to an IKeyEncryptionKey easily, and how?
  2. Can a key resolver be easily retrieved from the Azure SDKs, and how so?

I'm presuming there are ways to do this that don't involve creating our own implementations of the interfaces, but MS in their infinite wisdom didn't see fit to add those few lines to their documentation.

Upvotes: 1

Views: 1826

Answers (1)

Stanley Gong
Stanley Gong

Reputation: 12153

I write a simple demo for you. Just try the C# console app below about azure blob client-encryption with azure KeyVault:

using System;

using Azure.Identity;
using Azure.Security.KeyVault.Keys.Cryptography;
using Azure.Storage;
using Azure.Storage.Blobs;
using Azure.Storage.Blobs.Specialized;

namespace BlobEncyptionWithBlob
{
    class Program
    {
        
        static void Main(string[] args)
        {
            string keyVaultName = "";
            string keyName = "";
            string kvUri = "https://" + keyVaultName + ".vault.azure.net/keys/" + keyName;


            string storageConnStr = "";
            string containerName = "";
            string encyptBlob = "encypt.txt";
            string localblobPath = @"C:\Users\Administrator\Desktop\123.txt";
            string localblobPath2 = @"C:\Users\Administrator\Desktop\123-decode.txt";

            //Below is to use recommended OAuth2 approach
            //string clientID = "<OAuth Client ID>";
            //string clientSecret = "<OAuth Secret>";
            //string tenant = "<OAuth Tenant ID>";
            //var cred = new ClientSecretCredential(tenant, clientID, clientSecret);

            //This is what you use to directly replace older AppAuthentication
            var cred = new DefaultAzureCredential();
      
            CryptographyClient cryptoClient = new CryptographyClient(new Uri(kvUri), cred);
            KeyResolver keyResolver = new KeyResolver(cred);

            ClientSideEncryptionOptions encryptionOptions = new ClientSideEncryptionOptions(ClientSideEncryptionVersion.V1_0)
            {
                KeyEncryptionKey = cryptoClient,
                KeyResolver = keyResolver,
                KeyWrapAlgorithm = "RSA-OAEP"

            };

            BlobClientOptions options = new SpecializedBlobClientOptions() { ClientSideEncryption = encryptionOptions };


            var blobClient = new BlobServiceClient(storageConnStr,options).GetBlobContainerClient(containerName).GetBlobClient(encyptBlob);

            //upload local blob to container
            blobClient.Upload(localblobPath);

            //If you want to modify the meta data you have to copy the exisiting meta, think there is a bug in the library that will wipe out the encryptiondata metadata if you write your own meta
            var myMeta = new Dictionary<string, string>();
            myMeta.Add("comment", "dis file is da shiznit");
            foreach (var existingMeta in blobClient.GetProperties().Value.Metadata)
            {
                if (!myMeta.ContainsKey(existingMeta.Key))
                {
                    myMeta.Add(existingMeta.Key, existingMeta.Value);
                }
            }
            blobClient.SetMetadata(myMeta);

            //Download from container to see if it is decided
            blobClient.DownloadTo(localblobPath2);

        }
    }
}

Result:

My local .txt file content:

enter image description here

Upload to blob and its content, it has been encrypted :

enter image description here

Download to local again and its content, it has been decoded:

enter image description here

Upvotes: 5

Related Questions