在 Azure.Storage v12 中如何使用 Azure KeyVault 密钥解密 blob

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

我们的代码目前正在使用旧的 Microsoft.WindowsAzure.Storage 库访问 Azure 中的 blob 存储。我正在尝试使用新的 v12 Azure.Storage.Blobs 库来替换旧的,但是我不知道如何 decrypt/encrypt blob。 MS 文档 (https://docs.microsoft.com/en-us/azure/storage/blobs/storage-encrypt-decrypt-blobs-key-vault?tabs=dotnet) 说 v12 代码片段尚未准备好,因此没有代码示例。

旧代码是这样的:

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);

到目前为止,我在这里获得了新代码:

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>);

当然这会抛出异常,因为KeyVaultKey无法转换为IKeyEncryptionKey。所以我的问题是

  1. 能否将密钥轻松转换为 IKeyEncryptionKey,如何转换?
  2. 能否从 Azure SDK 轻松检索密钥解析器,如何检索?

我假设有一些方法可以做到这一点,而不涉及创建我们自己的接口实现,但 MS 以其无限的智慧认为不适合将那几行添加到他们的文档中。

我写了一个简单的演示给你。只需尝试下面有关使用 azure KeyVault 进行 azure blob 客户端加密的 C# 控制台应用程序:

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\Desktop3.txt";
            string localblobPath2 = @"C:\Users\Administrator\Desktop3-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);

        }
    }
}

结果:

我的本地 .txt 文件内容:

上传到 blob 及其内容,已加密:

重新下载到本地,内容已解码: