Azure Storage Account 提供了静态加密,其中密钥支持三种方式:
| Key management parameter | Microsoft-managed keys | Customer-managed keys | Customer-provided keys | 
|---|---|---|---|
| Encryption/decryption operations | Azure | Azure | Azure | 
| Azure Storage services supported | All | Blob storage, Azure Files1,2 | Blob storage | 
| Key storage | Microsoft key store | Azure Key Vault or Key Vault HSM | Customer's own key store | 
| Key rotation responsibility | Microsoft | Customer | Customer | 
| Key control | Microsoft | Customer | Customer | 
1 For information about creating an account that supports using customer-managed keys with Queue storage, see Create an account that supports customer-managed keys for queues.
2 For information about creating an account that supports using customer-managed keys with Table storage, see Create an account that supports customer-managed keys for tables.
上述三种加密方式在某些文档中也简写为 mmk,cmk,cpk。
直观的区别是:
1. MMK,Microsoft-managed keys,key的存储,替换由微软管理,用户无需关注密钥的维护。
2. CMK,Customer-managed keys,key由客户自己管理,一般放到key vault中,当需要更换时,在key vault中生成新的key,然后在 storage account的 配置页面修改key即可。

3. CPK, Customer-Provided keys,客户提供的key,这个是最为特殊的,需要在每一个读写请求中(写在代码或着调用api的时候),附加上key的信息,而且storage account中没有任何配置CPK的地方。
关于CPK的信息,请参考:https://docs.microsoft.com/zh-cn/azure/storage/blobs/encryption-customer-provided-keys?WT.mc_id=AZ-MVP-5003757
关于CPK的示例代码:
 class Program
    {
       async static Task Main(string[] args)
        {
            string filePath = "/Users/seanyu/Sean-Code/blob-enctyption-by-user-key/blob-encryption-by-user-key/blob-encryption-by-user-key/iothub.json";
            //string connectionString = "DefaultEndpointsProtocol=https;AccountName=seanstorage001;AccountKey=hGp6XxhfFEtpTQfm9rePGOeqZbwa6XFyz1+oUpwaVtLvd3yh9v247xQ7wZ1fU8c0Pw3nc/fMKCI9ySvgKj0EbQ==;EndpointSuffix=core.chinacloudapi.cn";
            string connectionString = "DefaultEndpointsProtocol=https;AccountName=seanstoragetest001;AccountKey=rqsoQkeTKnCMis6Ulu97EK30rsMhZVTEoT+uCvj6Sr2gA2vC0mh3oCqQlam5Ok2qHBHVOCQBJUhryMGY1t+J9w==;EndpointSuffix=core.chinacloudapi.cn";
            string containerName = "sample-container";
            string blobName = "sample-blob";
            string key = "MDEyMzQ1NjcwMTIzNDU2NzAxMjM0NTY3MDEyMzQ1Njc=";
            string keySha256 = "3QFFFpRA5+XANHqwwbT4yXDmrT/2JaLt/FKHjzhOdoE=";
            await  UploadBlobWithClientKey(connectionString,containerName,blobName,filePath,key,keySha256);
        }
        async static Task UploadBlobWithClientKey(string connectionString,
                                         string blobContainerName,
                                         string blobName,
                                         string filePath,
                                         string key,
                                         string keySha256)
        {
            // Create a new customer-provided key.
            // Key must be AES-256.
            var cpk = new CustomerProvidedKey(key);
            // Check the key's encryption hash.
            if (cpk.EncryptionKeyHash != keySha256)
            {
                throw new InvalidOperationException("The encryption key is corrupted.");
            }
            // Specify the customer-provided key on the options for the client.
            BlobClientOptions options = new BlobClientOptions()
            {
                CustomerProvidedKey = cpk
            };
            // Create the client object with options specified.
            BlobClient blobClient = new BlobClient(
                connectionString,blobContainerName,blobName,
                options);
            // If the container may not exist yet,
            // create a client object for the container.
            // The container client retains the credential and client options.
            BlobContainerClient containerClient =
                blobClient.GetParentBlobContainerClient();
            try
            {
                // Create the container if it does not exist.
                await containerClient.CreateIfNotExistsAsync();
                // Upload the data using the customer-provided key.
                await blobClient.UploadAsync(filePath);
                //download to local file
                await blobClient.DownloadToAsync("download.json");
            }
            catch (RequestFailedException e)
            {
                Console.WriteLine(e.Message);
                Console.ReadLine();
                throw;
            }
        }
    }
