/// <summary>
        /// Stores the provided XML element into S3.
        /// </summary>
        /// <param name="element">XML to store.</param>
        /// <param name="friendlyName">Friendly name of the XML (usually, ironically, a GUID).</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns></returns>
        public async Task StoreElementAsync(XElement element, string friendlyName, CancellationToken ct)
        {
            ValidateConfig();

            var key = Config.KeyPrefix + mockWrapper.GetNewGuid() + ".xml";

            logger?.LogDebug("Storing DataProtection key at S3 location {0} in bucket {1}, friendly name of {2} as metadata", key, Config.Bucket, friendlyName);

            var expectedMetadata = await PutElement(key, element, friendlyName, ct).ConfigureAwait(false);

            await CheckElement(key, expectedMetadata, ct).ConfigureAwait(false);
        }
        /// <summary>
        /// Stores the provided XML element into S3.
        /// </summary>
        /// <param name="element">XML to store.</param>
        /// <param name="friendlyName">Friendly name of the XML (usually, ironically, a GUID).</param>
        /// <param name="ct">Cancellation token.</param>
        /// <returns></returns>
        public async Task StoreElementAsync(XElement element, string friendlyName, CancellationToken ct)
        {
            var key = Config.KeyPrefix + mockWrapper.GetNewGuid() + ".xml";

            logger?.LogDebug("Storing DataProtection key at S3 location {0} in bucket {1}, friendly name of {2} as metadata", key, Config.Bucket, friendlyName);

            var pr = new PutObjectRequest
            {
                BucketName = Config.Bucket,
                Key        = key,
                ServerSideEncryptionMethod         = Config.ServerSideEncryptionMethod,
                ServerSideEncryptionCustomerMethod = ServerSideEncryptionCustomerMethod.None,
                AutoResetStreamPosition            = false,
                AutoCloseStream = true,
                ContentType     = "text/xml",
                StorageClass    = Config.StorageClass
            };

            pr.Metadata.Add(FriendlyNameMetadata, friendlyName);
            pr.Headers.ContentDisposition = "attachment; filename=" + friendlyName + ".xml";

            if (Config.ServerSideEncryptionMethod == ServerSideEncryptionMethod.AWSKMS)
            {
                pr.ServerSideEncryptionKeyManagementServiceKeyId = Config.ServerSideEncryptionKeyManagementServiceKeyId;
            }
            else if (Config.ServerSideEncryptionCustomerMethod != ServerSideEncryptionCustomerMethod.None)
            {
                pr.ServerSideEncryptionMethod                 = ServerSideEncryptionMethod.None;
                pr.ServerSideEncryptionCustomerMethod         = Config.ServerSideEncryptionCustomerMethod;
                pr.ServerSideEncryptionCustomerProvidedKey    = Config.ServerSideEncryptionCustomerProvidedKey;
                pr.ServerSideEncryptionCustomerProvidedKeyMD5 = Config.ServerSideEncryptionCustomerProvidedKeyMd5;
            }

            using (var outputStream = new MemoryStream())
            {
                if (Config.ClientSideCompression)
                {
                    // Enable S3 to serve the content so that it automatically unzips in browser
                    // Note that this doesn't apply to the streams AWS SDK returns!
                    // Also provides a very convenient discriminator for whether the key is compressed
                    pr.Headers.ContentEncoding = "gzip";
                    using (var inputStream = new MemoryStream())
                    {
                        using (var gZippedstream = new GZipStream(inputStream, CompressionMode.Compress, true))
                        {
                            element.Save(gZippedstream);
                        }
                        byte[] inputArray = inputStream.ToArray();
                        await outputStream.WriteAsync(inputArray, 0, inputArray.Length, ct);
                    }
                }
                else
                {
                    element.Save(outputStream);
                }

                outputStream.Seek(0, SeekOrigin.Begin);
                using (var hasher = MD5.Create())
                {
                    pr.MD5Digest = Convert.ToBase64String(hasher.ComputeHash(outputStream));
                }

                outputStream.Seek(0, SeekOrigin.Begin);
                pr.InputStream = outputStream;

                await s3Client.PutObjectAsync(pr, ct).ConfigureAwait(false);
            }
        }