Example #1
0
        public BlobDemo(string storageConnectionString)
        {
            this.storageConnectionString = storageConnectionString;

            // This creates a "key resolver" that we can use to to encrypt and decrypt blobs
            keyResolver = new KeyVaultKeyResolver(GetAuthToken);
        }
        private BlobEncryptionPolicy GetEncryptionPolicyForDownload()
        {
            var keyResolver          = new KeyVaultKeyResolver(_keyVaultClient);
            var blobEncryptionPolicy = new BlobEncryptionPolicy(null, keyResolver);

            return(blobEncryptionPolicy);
        }
        public FileStreamResult File(string filename)
        {
            var stockpickFormsAzurequeueConnectionstring = "Stockpick.Forms.AzureQueue.Connectionstring";
            var connectionstring = Sitecore.Configuration.Settings.GetSetting(stockpickFormsAzurequeueConnectionstring);

            Microsoft.WindowsAzure.Storage.CloudStorageAccount storageAccount = Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(connectionstring);

            var cloudBlobClient = storageAccount.CreateCloudBlobClient();
            var blobContainer   = cloudBlobClient.GetContainerReference("stockpickformsblob");

            blobContainer.CreateIfNotExists();

            var cloudResolver = new KeyVaultKeyResolver(Keyvault.GetToken);
            var url           = Sitecore.Configuration.Settings.GetSetting("Stockpick.Forms.KeyFault.Key.URL");

            if (string.IsNullOrEmpty(url))
            {
                Log.Error("config key Stockpick.Forms.KeyFault.Key.URL is emty", this);
            }
            var key = cloudResolver.ResolveKeyAsync(url, CancellationToken.None).GetAwaiter().GetResult();

            CloudBlockBlob blob = blobContainer.GetBlockBlobReference(filename);


            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            Stream blobStream = blob.OpenRead(null, options);

            return(new FileStreamResult(blobStream, "application/x-binary"));
        }
        public async Task <KeyValuePair <string, MemoryStream> > DownloadDocumentAsync(Guid documentId, Guid customerId)
        {
            var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["DocumentStore"].ConnectionString);
            var blobClient     = storageAccount.CreateCloudBlobClient();

            var container = blobClient.GetContainerReference(customerId.ToString().ToLower());

            var dbContext = new DashDocsContext();
            var document  = await dbContext.Documents.SingleAsync(d => d.Id == documentId);

            var keyvaultResolver = new KeyVaultKeyResolver(GetToken);

            var encryptionPolicy = new BlobEncryptionPolicy(null, keyvaultResolver);
            var requestOptions   = new BlobRequestOptions {
                EncryptionPolicy = encryptionPolicy
            };

            var block = container.GetBlockBlobReference(document.BlobPath);

            var stream = new MemoryStream();
            await block.DownloadToStreamAsync(stream, null, requestOptions, null);

            var content = new KeyValuePair <string, MemoryStream>(document.DocumentName, stream);

            return(content);
        }
        public async Task KeyVault_KeyVaultKeyResolver_Secret256Base64()
        {
            // Arrange
            var client = CreateKeyVaultClient();
            var vault  = ConfigurationManager.AppSettings["VaultUrl"];

            var keyBytes = new byte[256 >> 3];

            new RNGCryptoServiceProvider().GetNonZeroBytes(keyBytes);

            var secret = await client.SetSecretAsync(vault, "TestSecret", Convert.ToBase64String(keyBytes), null, "application/octet-stream").ConfigureAwait(false);

            if (secret != null)
            {
                try
                {
                    // ctor with client
                    var resolver = new KeyVaultKeyResolver(client);

                    var baseKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    var versionKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with authentication callback
                    resolver = new KeyVaultKeyResolver(GetAccessToken);

                    baseKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with vault name and client
                    resolver = new KeyVaultKeyResolver(vault, client);

                    baseKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with vault name and authentication callback
                    resolver = new KeyVaultKeyResolver(vault, GetAccessToken);

                    baseKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(secret.SecretIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);
                }
                finally
                {
                    // Delete the key
                    client.DeleteSecretAsync(vault, "TestSecret").GetAwaiter().GetResult();
                }
            }
        }
        public static IActionResult RunDecryptBlobFile(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
            ILogger log,
            ExecutionContext executionContext)
        {
            log.LogInformation("DecryptBlobFile Custom Skill: C# HTTP trigger function processed a request.");

            string skillName = executionContext.FunctionName;
            IEnumerable <WebApiRequestRecord> requestRecords = WebApiSkillHelpers.GetRequestRecords(req);

            if (requestRecords == null)
            {
                return(new BadRequestObjectResult($"{skillName} - Invalid request record array."));
            }

            // Set up access to keyvault to retrieve the key to decrypt the document with
            // Requires that this Azure Function has access via managed identity to the Keyvault where the key is stored.
            var azureServiceTokenProvider1 = new AzureServiceTokenProvider();
            var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider1.KeyVaultTokenCallback));
            KeyVaultKeyResolver  cloudResolver = new KeyVaultKeyResolver(kv);
            BlobEncryptionPolicy policy        = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options       = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            WebApiSkillResponse response = WebApiSkillHelpers.ProcessRequestRecords(skillName, requestRecords,
                                                                                    (inRecord, outRecord) =>
            {
                string blobUrl  = (inRecord.Data.TryGetValue("blobUrl", out object blobUrlObject) ? blobUrlObject : null) as string;
                string sasToken = (inRecord.Data.TryGetValue("sasToken", out object sasTokenObject) ? sasTokenObject : null) as string;

                if (string.IsNullOrWhiteSpace(blobUrl))
                {
                    outRecord.Errors.Add(new WebApiErrorWarningContract()
                    {
                        Message = $"Parameter '{nameof(blobUrl)}' is required to be present and a valid uri."
                    });
                    return(outRecord);
                }

                CloudBlockBlob blob = new CloudBlockBlob(new Uri(WebApiSkillHelpers.CombineSasTokenWithUri(blobUrl, sasToken)));
                byte[] decryptedFileData;
                using (var np = new MemoryStream())
                {
                    blob.DownloadToStream(np, null, options, null);
                    decryptedFileData = np.ToArray();
                }
                FileReference decryptedFileReference = new FileReference()
                {
                    data = Convert.ToBase64String(decryptedFileData)
                };
                JObject jObject  = JObject.FromObject(decryptedFileReference);
                jObject["$type"] = "file";
                outRecord.Data["decrypted_file_data"] = jObject;
                return(outRecord);
            });
        public async override Task ExecutePostProcessingAsync()
        {
            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(ServerUtils.GetToken);
            IKey rsa = await cloudResolver.ResolveKeyAsync(ConfidentialData.KeyLocation, CancellationToken.None);

            foreach (var file in FileData)
            {
                string fileName = Path.GetFileName(file.Headers.ContentDisposition.FileName.Trim('"'));
                var    blob     = _container.GetBlockBlobReference(Path.Combine(currentFilePath, fileName));

                BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(rsa, null);
                BlobRequestOptions   options = new BlobRequestOptions()
                {
                    EncryptionPolicy = policy
                };

                using (var stream = File.OpenRead(file.LocalFileName))
                {
                    await blob.UploadFromStreamAsync(stream, stream.Length, null, options, null);
                }

                Urls.Add(blob.Uri.AbsoluteUri);

                string ext = Path.GetExtension(fileName);

                if (ext == ".jpeg" || ext == ".jpg")
                {
                    Image original = Image.FromFile(file.LocalFileName);
                    float ratio    = (float)original.Width / (float)original.Height;
                    SizeF newSize  = new SizeF(350 * ratio, 350);

                    Image thumb = original.GetThumbnailImage((int)newSize.Width, (int)newSize.Height, null, IntPtr.Zero);

                    string thumbName = Path.GetFileNameWithoutExtension(fileName) + "_thumb.jpg";

                    var thumbBlob = _container.GetBlockBlobReference(Path.Combine(currentFilePath, thumbName));

                    MemoryStream thumbStream = new MemoryStream();

                    thumb.Save(thumbStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                    thumbStream.Position = 0;

                    await thumbBlob.UploadFromStreamAsync(thumbStream, thumbStream.Length, null, options, null);

                    Urls.Add(thumbBlob.Uri.AbsoluteUri);
                }

                try
                {
                    File.Delete(file.LocalFileName);
                }
                catch (Exception e)
                { }
            }
        }
        public async Task KeyVault_KeyVaultKeyResolver_Key()
        {
            // Arrange
            var client = CreateKeyVaultClient();
            var vault  = ConfigurationManager.AppSettings["VaultUrl"];

            var key = await client.CreateKeyAsync(vault, "TestKey", JsonWebKeyType.Rsa).ConfigureAwait(false);

            if (key != null)
            {
                try
                {
                    // ctor with client
                    var resolver = new KeyVaultKeyResolver(client);

                    var baseKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    var versionKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with authentication callback
                    resolver = new KeyVaultKeyResolver(GetAccessToken);

                    baseKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with vault name and client
                    resolver = new KeyVaultKeyResolver(vault, client);

                    baseKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);

                    // ctor with vault name and authentication callback
                    resolver = new KeyVaultKeyResolver(vault, GetAccessToken);

                    baseKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.BaseIdentifier, default(CancellationToken)).ConfigureAwait(false);

                    versionKey = await resolver.ResolveKeyAsync(key.KeyIdentifier.Identifier, default(CancellationToken)).ConfigureAwait(false);

                    Assert.Equal(baseKey.Kid, versionKey.Kid);
                }
                finally
                {
                    // Delete the key
                    client.DeleteKeyAsync(vault, "TestKey").GetAwaiter().GetResult();
                }
            }
        }
 public EncryptedFileContentRepository(
     string fileStorageKey,
     CloudBlobClient cloudBlobClient,
     IKeyVaultClient keyVaultClient,
     IBlobStorage blobStorage)
 {
     _fileStorageKey  = fileStorageKey;
     _cloudBlobClient = cloudBlobClient;
     _blobStorage     = blobStorage;
     _cloudResolver   = new KeyVaultKeyResolver(keyVaultClient);
 }
Example #10
0
        private static async Task UploadAndDownloadBlobAsync(TenantInfo tenant)
        {
            var container = await GetBlobContainerAsync(tenant.ContainerName);

            var  cloudResolver = new KeyVaultKeyResolver(GetTokenAsync);
            IKey key           = await cloudResolver.ResolveKeyAsync(GetKeyUrl(tenant.KeyName), CancellationToken.None);

            CloudBlob blob = await UploadBlobAsync(container, key);

            await DownloadBlobAsync(blob, cloudResolver);
        }
        private async Task <BlobEncryptionPolicy> GetEncryptionPolicyForUpload(EncryptedBlobAttribute config, string keyName, CancellationToken cancellationToken)
        {
            var kid = await _keyVaultClient.GetKidByName(config, keyName, cancellationToken) ?? throw new ArgumentException(nameof(EncryptedBlobAttribute.KeyName));

            var keyResolver = new KeyVaultKeyResolver(_keyVaultClient);
            var key         = await keyResolver.ResolveKeyAsync(kid, cancellationToken);

            var blobEncryptionPolicy = new BlobEncryptionPolicy(key, null);

            return(blobEncryptionPolicy);
        }
Example #12
0
        public async Task <HttpResponseMessage> Get(string imageId, bool thumb = false)
        {
            int id;

            if (string.IsNullOrEmpty(imageId) || !Int32.TryParse(imageId, out id))
            {
                return(Request.CreateResponse(HttpStatusCode.BadRequest));
            }

            ServiceData.Models.Photo found = _photoRepository.GetById(id);
            if (found == null)
            {
                return(Request.CreateResponse(HttpStatusCode.NotFound));
            }

            ServiceData.Models.UserCondition foundCond = _conditionRepository.GetById(found.UserCondition.Id);
            if (foundCond.Owner.Email != User.Identity.Name)
            {
                return(Request.CreateResponse(HttpStatusCode.Forbidden));
            }

            string target = (thumb) ? found.ThumbUrl : found.Url;

            CloudBlobContainer container = await GetBlobContainer();

            Stream    blobStream = new MemoryStream();
            CloudBlob photoBlob  = container.GetBlobReference(target.Replace(ConfidentialData.BlobStorageUrl, ""));

            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(ServerUtils.GetToken);
            IKey rsa = await cloudResolver.ResolveKeyAsync(ConfidentialData.KeyLocation, CancellationToken.None);

            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            await photoBlob.DownloadToStreamAsync(blobStream, null, options, null);

            blobStream.Position = 0;

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);

            response.Content = new StreamContent(blobStream);
            response.Content.Headers.ContentDisposition          = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment");
            response.Content.Headers.ContentDisposition.FileName = imageId + Path.GetExtension(target);

            string eventName = thumb ? "DownloadThumb" : "DownloadImage";

            ServerUtils.LogTelemetryEvent(User.Identity.Name, eventName);

            return(response);
        }
Example #13
0
        private static async Task DownloadBlobAsync(CloudBlob blob, KeyVaultKeyResolver cloudResolver)
        {
            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options = new BlobRequestOptions {
                EncryptionPolicy = policy
            };

            using (var np = File.Open("DownloadedData.txt", FileMode.Create))
            {
                await blob.DownloadToStreamAsync(np, null, options, null);
            }
        }
        static void Main(string[] args)
        {
            // This is standard code to interact with Blob storage.
            StorageCredentials creds = new StorageCredentials(
                CloudConfigurationManager.GetSetting("accountName"),
                CloudConfigurationManager.GetSetting("accountKey"));
            CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
            CloudBlobClient     client  = account.CreateCloudBlobClient();
            CloudBlobContainer  contain = client.GetContainerReference(CloudConfigurationManager.GetSetting("container"));

            contain.CreateIfNotExists();

            // The Resolver object is used to interact with Key Vault for Azure Storage.
            // This is where the GetToken method from above is used.
            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(GetToken);


            //Encrypt Blob and upload
            // Retrieve the key that you created previously.
            // The IKey that is returned here is an RsaKey.
            var rsa = cloudResolver.ResolveKeyAsync(
                "https://phupaa-vault.vault.azure.net/keys/key01",
                CancellationToken.None).GetAwaiter().GetResult();

            // Now you simply use the RSA key to encrypt by setting it in the BlobEncryptionPolicy.
            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(rsa, null);
            BlobRequestOptions   options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            // Reference a block blob.
            CloudBlockBlob blob = contain.GetBlockBlobReference("MyFile.txt");

            // Upload using the UploadFromStream method.
            using (var stream = System.IO.File.OpenRead(@"C:\Temp\MyFile.txt"))
                blob.UploadFromStream(stream, stream.Length, null, options, null);



            //Decrypt blob
            // In this case, we will not pass a key and only pass the resolver because
            // this policy will only be used for downloading / decrypting.
            BlobEncryptionPolicy policy2  = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options2 = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            using (var np = File.Open(@"C:\temp\MyFileDecrypted.txt", FileMode.Create))
                blob.DownloadToStream(np, null, options, null);
        }
        public void uploadBlob()
        {
            // This is standard code to interact with Blob storage.
            StorageCredentials creds = new StorageCredentials(
                ConfigurationManager.AppSettings["accountName"],
                ConfigurationManager.AppSettings["accountKey"]);
            CloudStorageAccount account = new CloudStorageAccount(creds, useHttps: true);
            CloudBlobClient     client  = account.CreateCloudBlobClient();
            CloudBlobContainer  contain = client.GetContainerReference(ConfigurationManager.AppSettings["container"]);

            contain.CreateIfNotExistsAsync();

            // The Resolver object is used to interact with Key Vault for Azure Storage.
            // This is where the GetToken method from above is used.
            cloudResolver = new KeyVaultKeyResolver(GetToken);
        }
Example #16
0
        //Read Encrypted blob to a Stream from a container
        public Stream GetBlobStream(string BlobName, string ContainerName, KeyVaultKeyResolver KeyResolver)
        {
            CloudBlobContainer container = GetContainerRefference(ContainerName);

            // In this case, we will not pass a key and only pass the resolver because
            // this policy will only be used for downloading / decrypting.
            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(null, KeyResolver);
            BlobRequestOptions   options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            // Retrieve reference to a blob named "myblob".
            CloudBlockBlob blob = container.GetBlockBlobReference(BlobName);

            return(blob.OpenRead(null, options, null));
        }
        internal static T Decrypt <T>(string encryptedData, KeyVaultKeyResolver cloudResolver, string keyId)
        {
            CipherData cb = Deserialize <CipherData>(encryptedData);
            IKey       keyEncryptionKey = null;

            try
            {
                keyEncryptionKey = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult();
                var currentKeyVersion = new Uri(keyEncryptionKey.Kid).Segments.Last();

                if (!currentKeyVersion.Equals(cb.KeyVersion))
                {
                    Console.WriteLine("Data encrypted with different key version: {0} vs {1}", currentKeyVersion, cb.KeyVersion);
                    // version doesn't match - go get the correct key version to unwrap with.
                    string newKey = keyId + "/" + cb.KeyVersion;
                    Console.WriteLine("Retrieving different key: " + newKey);
                    try
                    {
                        keyEncryptionKey = cloudResolver.ResolveKeyAsync(newKey, CancellationToken.None).GetAwaiter().GetResult();
                    }
                    catch (AggregateException ae)
                    {
                        Console.WriteLine("Cloudresolver could not retrieve key, version '" + cb.KeyVersion + "': " + ae.Message);
                        return(default(T));
                    }
                }

                // Unwrap Key using KeyVault
                byte[] aesKey = keyEncryptionKey.UnwrapKeyAsync(Convert.FromBase64String(cb.WrapedKey), cb.AlgorithmName, CancellationToken.None).GetAwaiter().GetResult();

                string plainJson = Decrypt(Convert.FromBase64String(cb.CipherText), aesKey);

                using (var streamReader = new StringReader(plainJson))
                {
                    JsonReader jreader = new JsonTextReader(streamReader);
                    return(new JsonSerializer().Deserialize <T>(jreader));
                }
            }
            finally
            {
                if (keyEncryptionKey != null)
                {
                    keyEncryptionKey.Dispose();
                }
            }
        }
Example #18
0
        public async Task <ActionResult> Download(string imageId, bool thumb = false)
        {
            int id;

            if (string.IsNullOrEmpty(imageId) || !Int32.TryParse(imageId, out id))
            {
                return(new HttpUnauthorizedResult());
            }

            IReadWriteRepository <ServiceData.Models.Photo>         _photoRepository = new PhotoRepository();
            IReadWriteRepository <ServiceData.Models.UserCondition> _condRepository  = new UserConditionsRepository();

            ServiceData.Models.Photo found = _photoRepository.GetById(id);
            if (found == null)
            {
                return(new HttpNotFoundResult());
            }

            ServiceData.Models.UserCondition foundCond = _condRepository.GetById(found.UserCondition.Id);
            if (!IsSharedOrOwned(foundCond))
            {
                return(new HttpUnauthorizedResult());
            }

            string target = (thumb) ? found.ThumbUrl : found.Url;

            CloudBlobContainer container = await UploadController.GetBlobContainer();

            Stream    blobStream = new MemoryStream();
            CloudBlob photoBlob  = container.GetBlobReference(target.Replace(ConfidentialData.BlobStorageUrl, ""));

            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(ServerUtils.GetToken);
            IKey rsa = await cloudResolver.ResolveKeyAsync(ConfidentialData.KeyLocation, CancellationToken.None);

            BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(null, cloudResolver);
            BlobRequestOptions   options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            await photoBlob.DownloadToStreamAsync(blobStream, null, options, null);

            blobStream.Position = 0;

            return(File(blobStream, "image/jpeg"));
        }
        private static async Task <string> RetrieveAndDecrypt(CloudBlobContainer blobContainer, string id)
        {
            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var client   = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            var resolver = new KeyVaultKeyResolver(client);
            //no need to provide key vault key id - stored in blob meta data
            var policy  = new BlobEncryptionPolicy(null, resolver);
            var options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };
            var blobRef = blobContainer.GetBlockBlobReference(id);
            var ms      = new MemoryStream();
            await blobRef.DownloadToStreamAsync(ms, null, options, null);

            return(Encoding.UTF8.GetString(ms.ToArray()));
        }
Example #20
0
        private void VerifyResolver(KeyVaultClient client, string vault, string baseIdentifier, string identifier)
        {
            // ctor with client
            var resolver = new KeyVaultKeyResolver(client);

            var baseKey    = resolver.ResolveKeyAsync(baseIdentifier, default(CancellationToken)).GetAwaiter().GetResult();
            var versionKey = resolver.ResolveKeyAsync(identifier, default(CancellationToken)).GetAwaiter().GetResult();

            Assert.Equal(baseKey.Kid, versionKey.Kid);

            // NOTE: ctor with authentication callback. We cannot test this ctor unless
            //       we are running in live mode as it will create a new KeyVaultClient.
            if (HttpMockServer.Mode == HttpRecorderMode.Record)
            {
                resolver = new KeyVaultKeyResolver(fixture.GetAccessToken);

                baseKey    = resolver.ResolveKeyAsync(baseIdentifier, default(CancellationToken)).GetAwaiter().GetResult();
                versionKey = resolver.ResolveKeyAsync(identifier, default(CancellationToken)).GetAwaiter().GetResult();

                Assert.Equal(baseKey.Kid, versionKey.Kid);
            }

            // ctor with vault name and client
            resolver = new KeyVaultKeyResolver(vault, client);

            baseKey    = resolver.ResolveKeyAsync(baseIdentifier, default(CancellationToken)).GetAwaiter().GetResult();
            versionKey = resolver.ResolveKeyAsync(identifier, default(CancellationToken)).GetAwaiter().GetResult();

            Assert.Equal(baseKey.Kid, versionKey.Kid);

            // NOTE: ctor with authentication callback. We cannot test this ctor unless
            //       we are running in live mode as it will create a new KeyVaultClient.
            if (HttpMockServer.Mode == HttpRecorderMode.Record)
            {
                resolver = new KeyVaultKeyResolver(vault, fixture.GetAccessToken);

                baseKey    = resolver.ResolveKeyAsync(baseIdentifier, default(CancellationToken)).GetAwaiter().GetResult();
                versionKey = resolver.ResolveKeyAsync(identifier, default(CancellationToken)).GetAwaiter().GetResult();

                Assert.Equal(baseKey.Kid, versionKey.Kid);
            }

            baseKey.Dispose();
            versionKey.Dispose();
        }
Example #21
0
        //carregar blog e chave do keyvault
        public void Start()
        {
            try
            {
                log.LogInformation("iniciando procesos de criação da chave base64");

                log.LogInformation("recebendo parametros [accounteName] e [accountKey]");

                // This is standard code to interact with Blob storage.
                var creds = new StorageCredentials(app.AccountName, app.AccountKey);

                var account = new CloudStorageAccount(creds, useHttps: true);

                log.LogInformation($"credencial validada para a conta {app.AccountName}");

                log.LogInformation("criando cliente de conexão ao storage");

                var client = account.CreateCloudBlobClient();

                log.LogInformation("cliente conectado");

                log.LogInformation("localizando container de referencia");

                log.LogInformation("recebendo parametros [container]");

                var contain = client.GetContainerReference(app.Container);

                contain.CreateIfNotExists();

                log.LogInformation($"container localizado para {app.Container}");

                // The Resolver object is used to interact with Key Vault for Azure Storage.
                // This is where the GetToken method from above is used.
                var cloudResolver = new KeyVaultKeyResolver(GetToken);

                RetriveRSA(cloudResolver, contain);
            }
            catch (Exception e)
            {
                log.LogError(e, "falha ao processar informações da chave, verifique os dados e tente novamente");
            }
        }
        // Encrypts an Object and retunrs a JSON object holding the encryption
        internal static string Encrypt(object o, KeyVaultKeyResolver cloudResolver, string keyId)
        {
            string jsonStringToEncrypt = Utils.Serialize(o);

            // Generate Client Encryption Key (CEK)
            using (var random = new RNGCryptoServiceProvider())
            {
                var aeskey = new byte[KEY_SIZE_BYTES];
                try
                {
                    // Generate an 256 bit AES Key
                    random.GetBytes(aeskey);

                    // Encrypt the plaintext
                    string cipherText = Convert.ToBase64String(Encrypt(jsonStringToEncrypt, aeskey));

                    Console.WriteLine("Retrieving key: " + keyId);
                    using (var keyEncryptionKey = cloudResolver.ResolveKeyAsync(keyId, CancellationToken.None).GetAwaiter().GetResult())
                    {
                        Console.WriteLine("Retrived key: " + keyEncryptionKey.Kid);
                        // Take the AES Key we Generated and Encrypt it using KeyVault to wrap it.
                        Tuple <byte[], string> wrappedKey = keyEncryptionKey.WrapKeyAsync(aeskey, null /* algorithm */, CancellationToken.None).GetAwaiter().GetResult();

                        string     keyVersion = new Uri(keyEncryptionKey.Kid).Segments.Last();
                        CipherData cb         = new CipherData {
                            AlgorithmName = wrappedKey.Item2, WrapedKey = Convert.ToBase64String(wrappedKey.Item1), CipherText = cipherText, KeyVersion = keyVersion
                        };

                        // TODO: Determine if the CipherData should contain a signature to prevent tampering.
                        // Need to enumerate the risks.

                        return(Utils.Serialize(cb));
                    }
                }
                finally
                {
                    // Clear out the key material from memory
                    Array.Clear(aeskey, 0, aeskey.Length);
                }
            }
        }
Example #23
0
        private void RetriveRSA(KeyVaultKeyResolver cloudResolver, CloudBlobContainer contain)
        {
            log.LogInformation($"validando chave externa de integração rsa");

            log.LogInformation("recebendo parametros [endpoint]");

            // Retrieve the key that you created previously.
            // The IKey that is returned here is an RsaKey.
            var rsa = cloudResolver.ResolveKeyAsync(app.Endpoint, CancellationToken.None)
                      .GetAwaiter().GetResult();

            log.LogInformation($"chave rsa gerada com sucesso");
            log.LogInformation($"algoritimo {rsa.DefaultEncryptionAlgorithm}");
            log.LogInformation($"hash {rsa.DefaultKeyWrapAlgorithm}");
            log.LogInformation($"assinatura {rsa.DefaultSignatureAlgorithm}");

            // Now you simply use the RSA key to encrypt by setting it in the BlobEncryptionPolicy.
            var policy  = new BlobEncryptionPolicy(rsa, null);
            var options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            log.LogInformation($"iniciando teste de upload no blob com autenticação segura");

            log.LogInformation($"validando referencia do blob para File.txt");

            // Reference a block blob.
            CloudBlockBlob blob = contain.GetBlockBlobReference("File.txt");

            log.LogInformation($"iniciando processo de upload");

            // Upload using the UploadFromStream method.
            using var stream = File.OpenRead(Directory.GetCurrentDirectory() + "\\File.txt");
            blob.UploadFromStream(stream, stream.Length, null, options, null);

            log.LogInformation($"valide se o arquivo File.txt é ");
        }
        private static async Task EncryptAndStore(CloudBlobContainer blobContainer, string text, string id)
        {
            var azureServiceTokenProvider = new AzureServiceTokenProvider();
            var client   = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
            var resolver = new KeyVaultKeyResolver(client);

            var rsa = await resolver.ResolveKeyAsync(Environment.GetEnvironmentVariable("RsaVaultKey"), CancellationToken.None);

            var policy  = new BlobEncryptionPolicy(rsa, null);
            var options = new BlobRequestOptions()
            {
                EncryptionPolicy = policy
            };

            var blob = blobContainer.GetBlockBlobReference(id);

            var bytes = Encoding.UTF8.GetBytes(text);

            using (Stream stream = new MemoryStream(bytes))
            {
                await blob.UploadFromStreamAsync(stream, bytes.Length, null, options, null);
            }
        }
        private void StoreFiles(CloudStorageAccount storageAccount, FormSubmitContext formSubmitContext, IEnumerable <Guid> fileIds)
        {
            var cloudBlobClient = storageAccount.CreateCloudBlobClient();
            var blob            = cloudBlobClient.GetContainerReference("stockpickformsblob");

            blob.CreateIfNotExists();

            var cloudResolver = new KeyVaultKeyResolver(Keyvault.GetToken);
            var url           = Sitecore.Configuration.Settings.GetSetting("Stockpick.Forms.KeyFault.Key.URL");

            if (string.IsNullOrEmpty(url))
            {
                Log.Error("config key Stockpick.Forms.KeyFault.Key.URL is emty", this);
            }
            var key = cloudResolver.ResolveKeyAsync(url, CancellationToken.None).GetAwaiter().GetResult();

            foreach (var gui in fileIds)
            {
                var file = FileStorageProvider.GetFile(gui);
                if (file != null)
                {
                    Log.Info("Upload to Cloud storage file " + file.FileInfo.FileName + " as " + gui.ToString() + " using key kid:" + key.Kid, this);

                    BlobEncryptionPolicy policy  = new BlobEncryptionPolicy(key, null);
                    BlobRequestOptions   options = new BlobRequestOptions()
                    {
                        EncryptionPolicy = policy
                    };

                    CloudBlockBlob cloudBlockBlob = blob.GetBlockBlobReference(gui.ToString());
                    using (var filestream = file.File)
                    {
                        cloudBlockBlob.UploadFromStream(filestream, null, options, null);
                    }
                }
            }
        }
Example #26
0
        public async Task <string> UploadDocumentAsync(HttpPostedFileBase documentFile, Guid customerId, Guid documentId)
        {
            var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["DocumentStore"].ConnectionString);
            var blobClient     = storageAccount.CreateCloudBlobClient();

            var container = blobClient.GetContainerReference(customerId.ToString().ToLower());
            await container.CreateIfNotExistsAsync();

            var keyvaultResolver = new KeyVaultKeyResolver(GetToken);
            var key = await keyvaultResolver.ResolveKeyAsync(KEY_URI, CancellationToken.None);

            var encryptionPolicy = new BlobEncryptionPolicy(key, null);
            var requestOptions   = new BlobRequestOptions {
                EncryptionPolicy = encryptionPolicy
            };

            var blobRelativePath = documentId.ToString().ToLower() + "/" + Path.GetFileName(documentFile.FileName).ToLower();

            var block = container.GetBlockBlobReference(blobRelativePath);

            await block.UploadFromStreamAsync(documentFile.InputStream, documentFile.InputStream.Length, null, requestOptions, null);

            return(blobRelativePath);
        }
Example #27
0
        // Required Nuget Pacakges:
        //
        // PM> Install-Package Microsoft.Azure.KeyVault
        // PM> Install-Package Microsoft.Azure.KeyVault.Extensions
        // PM> This is the latest stable release for ADAL
        //
        // (AuthenticationContext, ClientCredential, AuthenticationResult)
        //
        // PM> Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory -Version 2.16.204221202
        static void Main(string[] args)
        {
            // Get a ref to the cloudResolver used to unwrap AES key using RSA
            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(Utils.GetToken);
            string keyId = ConfigurationManager.AppSettings["KeyUri"];

            // Create an object to Serialize to JSON and then Encrypt
            CredentialData cb = new CredentialData {
                UserName = "******", Password = "******"
            };

            Console.WriteLine("Object to encrypt...");
            Console.WriteLine("UserName: "******" Password: "******"C:\code\temp\Nexosis-Wallpaper";
            string fileToEncrypt       = baseFileName + ".jpg";
            string encryptedOutputFile = baseFileName + ".aes";

            Console.WriteLine("Encrypting file: " + fileToEncrypt);
            string encryptedmetaData = Utils.EncryptFile(fileToEncrypt, encryptedOutputFile, cloudResolver, keyId);

            Console.WriteLine("Encrypted file: " + encryptedOutputFile);
            Console.WriteLine(encryptedmetaData);
            Console.WriteLine();

            string decryptedOutput = encryptedOutputFile + "2.jpg";

            Console.WriteLine("Decrypting file: " + encryptedOutputFile);
            Utils.DecryptFile(encryptedOutputFile, encryptedmetaData, decryptedOutput, cloudResolver, keyId);
            Console.WriteLine("Decrypted file: " + decryptedOutput);
            Console.WriteLine();

            Console.WriteLine("Encrypting object...");
            // Serialize and Encrypt
            string encryptedCredential = Utils.Encrypt(cb, cloudResolver, keyId);

            Console.WriteLine("Encrypted:");
            Console.WriteLine(encryptedCredential);
            Console.WriteLine();

            Console.WriteLine("Decrypting object...");
            // Take an encrypted object Decrypt an deserialize back to obj type
            CredentialData cb2 = Utils.Decrypt <CredentialData>(encryptedCredential, cloudResolver, keyId);

            Console.WriteLine("UserName: "******" Password: "******"Decrypting stored data that has an older key version.");
            string decryptThis = File.ReadAllText("creds.json");
            // Take an encrypted object Decrypt an deserialize back to obj type with different version
            CredentialData cb3 = Utils.Decrypt <CredentialData>(decryptThis, cloudResolver, keyId);

            if (cb3 != null)
            {
                Console.WriteLine("UserName: "******" Password: " + cb3.Password);
            }

            Console.ReadLine();
        }
Example #28
0
        static void Main(string[] args)
        {
            Console.WriteLine("Blob encryption with Key Vault integration");
            Console.WriteLine();

            // Get the key ID from App.config if it exists.
            string keyID = CloudConfigurationManager.GetSetting("KeyID");

            // If no key ID was specified, we will create a new secret in Key Vault.
            // To create a new secret, this client needs full permission to Key Vault secrets.
            // Once the secret is created, its ID can be added to App.config. Once this is done,
            // this client only needs read access to secrets.
            if (string.IsNullOrEmpty(keyID))
            {
                Console.WriteLine("No secret specified in App.config.");
                Console.WriteLine("Please enter the name of a new secret to create in Key Vault.");
                Console.WriteLine("WARNING: This will delete any existing secret with the same name.");
                Console.Write("Name of the new secret to create [{0}]: ", DefaultSecretName);
                string newSecretName = Console.ReadLine().Trim();

                if (string.IsNullOrEmpty(newSecretName))
                {
                    newSecretName = DefaultSecretName;
                }

                // Although it is possible to use keys (rather than secrets) stored in Key Vault, this prevents caching.
                // Therefore it is recommended to use secrets along with a caching resolver (see below).
                keyID = EncryptionShared.KeyVaultUtility.SetUpKeyVaultSecret(newSecretName);

                Console.WriteLine();
                Console.WriteLine("Created a secret with ID: {0}", keyID);
                Console.WriteLine("Copy the secret ID to App.config to reuse.");
                Console.WriteLine();
            }

            // Retrieve storage account information from connection string
            // How to create a storage connection string - https://azure.microsoft.com/en-us/documentation/articles/storage-configure-connection-string/
            CloudStorageAccount storageAccount = EncryptionShared.Utility.CreateStorageAccountFromConnectionString();

            CloudBlobClient    client    = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer container = client.GetContainerReference(DemoContainer + Guid.NewGuid().ToString("N"));

            // Construct a resolver capable of looking up keys and secrets stored in Key Vault.
            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(EncryptionShared.KeyVaultUtility.GetAccessToken);

            // To demonstrate how multiple different types of key can be used, we also create a local key and resolver.
            // This key is temporary and won't be persisted.
            RsaKey        rsaKey   = new RsaKey("rsakey");
            LocalResolver resolver = new LocalResolver();

            resolver.Add(rsaKey);

            // If there are multiple key sources like Azure Key Vault and local KMS, set up an aggregate resolver as follows.
            // This helps users to define a plug-in model for all the different key providers they support.
            AggregateKeyResolver aggregateResolver = new AggregateKeyResolver()
                                                     .Add(resolver)
                                                     .Add(cloudResolver);

            // Set up a caching resolver so the secrets can be cached on the client. This is the recommended usage
            // pattern since the throttling targets for Storage and Key Vault services are orders of magnitude
            // different.
            CachingKeyResolver cachingResolver = new CachingKeyResolver(2, aggregateResolver);

            // Create a key instance corresponding to the key ID. This will cache the secret.
            IKey cloudKey = cachingResolver.ResolveKeyAsync(keyID, CancellationToken.None).GetAwaiter().GetResult();

            try
            {
                container.Create();
                int    size   = 5 * 1024 * 1024;
                byte[] buffer = new byte[size];

                Random rand = new Random();
                rand.NextBytes(buffer);

                // The first blob will use the key stored in Azure Key Vault.
                CloudBlockBlob blob = container.GetBlockBlobReference("blockblob1");

                // Create the encryption policy using the secret stored in Azure Key Vault to be used for upload.
                BlobEncryptionPolicy uploadPolicy = new BlobEncryptionPolicy(cloudKey, null);

                // Set the encryption policy on the request options.
                BlobRequestOptions uploadOptions = new BlobRequestOptions()
                {
                    EncryptionPolicy = uploadPolicy
                };

                Console.WriteLine("Uploading the 1st encrypted blob.");

                // Upload the encrypted contents to the blob.
                using (MemoryStream stream = new MemoryStream(buffer))
                {
                    blob.UploadFromStream(stream, size, null, uploadOptions);
                }

                // Download the encrypted blob.
                BlobEncryptionPolicy downloadPolicy = new BlobEncryptionPolicy(null, cachingResolver);

                // Set the decryption policy on the request options.
                BlobRequestOptions downloadOptions = new BlobRequestOptions()
                {
                    EncryptionPolicy = downloadPolicy
                };

                Console.WriteLine("Downloading the 1st encrypted blob.");

                // Download and decrypt the encrypted contents from the blob.
                using (MemoryStream outputStream = new MemoryStream())
                {
                    blob.DownloadToStream(outputStream, null, downloadOptions);
                }

                // Upload second blob using the local key.
                blob = container.GetBlockBlobReference("blockblob2");

                // Create the encryption policy using the local key.
                uploadPolicy = new BlobEncryptionPolicy(rsaKey, null);

                // Set the encryption policy on the request options.
                uploadOptions = new BlobRequestOptions()
                {
                    EncryptionPolicy = uploadPolicy
                };

                Console.WriteLine("Uploading the 2nd encrypted blob.");

                // Upload the encrypted contents to the blob.
                using (MemoryStream stream = new MemoryStream(buffer))
                {
                    blob.UploadFromStream(stream, size, null, uploadOptions);
                }

                // Download the encrypted blob. The same policy and options created before can be used because the aggregate resolver contains both
                // resolvers and will pick the right one based on the key ID stored in blob metadata on the service.
                Console.WriteLine("Downloading the 2nd encrypted blob.");

                // Download and decrypt the encrypted contents from the blob.
                using (MemoryStream outputStream = new MemoryStream())
                {
                    blob.DownloadToStream(outputStream, null, downloadOptions);
                }

                Console.WriteLine("Press enter key to exit");
                Console.ReadLine();
            }
            finally
            {
                container.DeleteIfExists();
            }
        }
Example #29
0
 public GlobalKeyResolver(KeyVaultProvider provider)
 {
     _provider = provider;
     _resolver = new KeyVaultKeyResolver(_provider.Client);
 }
Example #30
0
        static void Main(string[] args)
        {
            Console.WriteLine("Blob encryption with Key Vault integration demonstrating key rotation from Key 1 to Key 2");
            Console.WriteLine();

            // Create two secrets and obtain their IDs. This is normally a one-time setup step.
            // Although it is possible to use keys (rather than secrets) stored in Key Vault, this prevents caching.
            // Therefore it is recommended to use secrets along with a caching resolver (see below).
            string keyID1 = EncryptionShared.KeyVaultUtility.SetUpKeyVaultSecret("KeyRotationSampleSecret1");
            string keyID2 = EncryptionShared.KeyVaultUtility.SetUpKeyVaultSecret("KeyRotationSampleSecret2");

            // Retrieve storage account information from connection string
            // How to create a storage connection string - https://azure.microsoft.com/en-us/documentation/articles/storage-configure-connection-string/
            CloudStorageAccount storageAccount = EncryptionShared.Utility.CreateStorageAccountFromConnectionString();
            CloudBlobClient     client         = storageAccount.CreateCloudBlobClient();
            CloudBlobContainer  container      = client.GetContainerReference(DemoContainer + Guid.NewGuid().ToString("N"));

            // Construct a resolver capable of looking up keys and secrets stored in Key Vault.
            KeyVaultKeyResolver cloudResolver = new KeyVaultKeyResolver(EncryptionShared.KeyVaultUtility.GetAccessToken);

            // Set up a caching resolver so the secrets can be cached on the client. This is the recommended usage
            // pattern since the throttling targets for Storage and Key Vault services are orders of magnitude
            // different.
            CachingKeyResolver cachingResolver = new CachingKeyResolver(2, cloudResolver);

            // Create key instances corresponding to the key IDs. This will cache the secrets.
            IKey cloudKey1 = cachingResolver.ResolveKeyAsync(keyID1, CancellationToken.None).GetAwaiter().GetResult();
            IKey cloudKey2 = cachingResolver.ResolveKeyAsync(keyID2, CancellationToken.None).GetAwaiter().GetResult();

            // We begin with cloudKey1, and a resolver capable of resolving and caching Key Vault secrets.
            BlobEncryptionPolicy encryptionPolicy = new BlobEncryptionPolicy(cloudKey1, cachingResolver);

            client.DefaultRequestOptions.EncryptionPolicy  = encryptionPolicy;
            client.DefaultRequestOptions.RequireEncryption = true;

            try
            {
                container.Create();
                int    size    = 5 * 1024 * 1024;
                byte[] buffer1 = new byte[size];
                byte[] buffer2 = new byte[size];

                Random rand = new Random();
                rand.NextBytes(buffer1);
                rand.NextBytes(buffer2);

                // Upload the first blob using the secret stored in Azure Key Vault.
                CloudBlockBlob blob = container.GetBlockBlobReference("blockblob1");

                Console.WriteLine("Uploading Blob 1 using Key 1.");

                // Upload the encrypted contents to the first blob.
                using (MemoryStream stream = new MemoryStream(buffer1))
                {
                    blob.UploadFromStream(stream, size);
                }

                Console.WriteLine("Downloading and decrypting Blob 1.");

                // Download and decrypt the encrypted contents from the first blob.
                using (MemoryStream outputStream = new MemoryStream())
                {
                    blob.DownloadToStream(outputStream);
                }

                // At this point we will rotate our keys so new encrypted content will use the
                // second key. Note that the same resolver is used, as this resolver is capable
                // of decrypting blobs encrypted using either key.
                Console.WriteLine("Rotating the active encryption key to Key 2.");

                client.DefaultRequestOptions.EncryptionPolicy = new BlobEncryptionPolicy(cloudKey2, cachingResolver);

                // Upload the second blob using the key stored in Azure Key Vault.
                CloudBlockBlob blob2 = container.GetBlockBlobReference("blockblob2");

                Console.WriteLine("Uploading Blob 2 using Key 2.");

                // Upload the encrypted contents to the second blob.
                using (MemoryStream stream = new MemoryStream(buffer2))
                {
                    blob2.UploadFromStream(stream, size);
                }

                Console.WriteLine("Downloading and decrypting Blob 2.");

                // Download and decrypt the encrypted contents from the second blob.
                using (MemoryStream outputStream = new MemoryStream())
                {
                    blob2.DownloadToStream(outputStream);
                }

                // Here we download and re-upload the first blob. This has the effect of updating
                // the blob to use the new key.
                using (MemoryStream memoryStream = new MemoryStream())
                {
                    Console.WriteLine("Downloading and decrypting Blob 1.");
                    blob.DownloadToStream(memoryStream);

                    memoryStream.Seek(0, SeekOrigin.Begin);

                    Console.WriteLine("Re-uploading Blob 1 using Key 2.");
                    blob.UploadFromStream(memoryStream);
                }

                // For the purposes of demonstration, we now override the encryption policy to only recognize key 2.
                BlobEncryptionPolicy key2OnlyPolicy  = new BlobEncryptionPolicy(cloudKey2, null);
                BlobRequestOptions   key2OnlyOptions = new BlobRequestOptions()
                {
                    EncryptionPolicy = key2OnlyPolicy
                };

                Console.WriteLine("Downloading and decrypting Blob 1.");

                // The first blob can still be decrypted because it is using the second key.
                using (MemoryStream outputStream = new MemoryStream())
                {
                    blob.DownloadToStream(outputStream, options: key2OnlyOptions);
                }

                Console.WriteLine("Press enter key to exit");
                Console.ReadLine();
            }
            finally
            {
                container.DeleteIfExists();
            }
        }