BlobClientSideDecryptor
                    class BlobClientSideDecryptor
                
                using Azure.Storage.Common;
using Azure.Storage.Cryptography;
using Azure.Storage.Cryptography.Models;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
namespace Azure.Storage.Blobs
{
    internal class BlobClientSideDecryptor
    {
        private readonly ClientSideDecryptor _decryptor;
        public BlobClientSideDecryptor(ClientSideDecryptor decryptor)
        {
            _decryptor = decryptor;
        }
        [AsyncStateMachine(typeof(<DecryptInternal>d__2))]
        public Task<Stream> DecryptInternal(Stream content, IDictionary<string, string> metadata, HttpRange originalRange, string receivedContentRange, bool async, CancellationToken cancellationToken)
        {
            <DecryptInternal>d__2 stateMachine = default(<DecryptInternal>d__2);
            stateMachine.<>t__builder = AsyncTaskMethodBuilder<Stream>.Create();
            stateMachine.<>4__this = this;
            stateMachine.content = content;
            stateMachine.metadata = metadata;
            stateMachine.originalRange = originalRange;
            stateMachine.receivedContentRange = receivedContentRange;
            stateMachine.async = async;
            stateMachine.cancellationToken = cancellationToken;
            stateMachine.<>1__state = -1;
            stateMachine.<>t__builder.Start(ref stateMachine);
            return stateMachine.<>t__builder.Task;
        }
        [AsyncStateMachine(typeof(<DecryptWholeBlobWriteInternal>d__3))]
        public Task<Stream> DecryptWholeBlobWriteInternal(Stream plaintextDestination, IDictionary<string, string> metadata, bool async, CancellationToken cancellationToken)
        {
            <DecryptWholeBlobWriteInternal>d__3 stateMachine = default(<DecryptWholeBlobWriteInternal>d__3);
            stateMachine.<>t__builder = AsyncTaskMethodBuilder<Stream>.Create();
            stateMachine.<>4__this = this;
            stateMachine.plaintextDestination = plaintextDestination;
            stateMachine.metadata = metadata;
            stateMachine.async = async;
            stateMachine.cancellationToken = cancellationToken;
            stateMachine.<>1__state = -1;
            stateMachine.<>t__builder.Start(ref stateMachine);
            return stateMachine.<>t__builder.Task;
        }
        [AsyncStateMachine(typeof(<TrimStreamInternal>d__4))]
        private static Task<Stream> TrimStreamInternal(Stream stream, HttpRange originalRange, ContentRange? receivedRange, int alreadyTrimmedOffsetAmount, bool async, CancellationToken cancellationToken)
        {
            <TrimStreamInternal>d__4 stateMachine = default(<TrimStreamInternal>d__4);
            stateMachine.<>t__builder = AsyncTaskMethodBuilder<Stream>.Create();
            stateMachine.stream = stream;
            stateMachine.originalRange = originalRange;
            stateMachine.receivedRange = receivedRange;
            stateMachine.alreadyTrimmedOffsetAmount = alreadyTrimmedOffsetAmount;
            stateMachine.async = async;
            stateMachine.cancellationToken = cancellationToken;
            stateMachine.<>1__state = -1;
            stateMachine.<>t__builder.Start(ref stateMachine);
            return stateMachine.<>t__builder.Task;
        }
        internal static EncryptionData GetAndValidateEncryptionDataOrDefault(IDictionary<string, string> metadata)
        {
            if (metadata == null)
                return null;
            if (!metadata.TryGetValue("encryptiondata", out string value))
                return null;
            EncryptionData encryptionData = EncryptionDataSerializer.Deserialize(value);
            switch (encryptionData.EncryptionAgent.EncryptionVersion) {
            case ClientSideEncryptionVersionInternal.V1_0:
                if (encryptionData.ContentEncryptionIV == null)
                    throw Errors.ClientSideEncryption.MissingEncryptionMetadata("ContentEncryptionIV");
                break;
            case ClientSideEncryptionVersionInternal.V2_0:
            case ClientSideEncryptionVersionInternal.V2_1:
                if (encryptionData.EncryptedRegionInfo == null)
                    throw Errors.ClientSideEncryption.MissingEncryptionMetadata("EncryptedRegionInfo");
                break;
            default:
                throw Errors.ClientSideEncryption.ClientSideEncryptionVersionNotSupported(null);
            }
            if (encryptionData.WrappedContentKey.EncryptedKey == null)
                throw Errors.ClientSideEncryption.MissingEncryptionMetadata("EncryptedKey");
            return encryptionData;
        }
        private static bool CanIgnorePadding(ContentRange? contentRange)
        {
            if (!contentRange.HasValue)
                return false;
            ContentRange value = contentRange.Value;
            if (!value.End.HasValue)
                return false;
            value = contentRange.Value;
            long? size = value.Size;
            value = contentRange.Value;
            long? nullable = size - value.End;
            long num = 1;
            if ((nullable.GetValueOrDefault() == num) & nullable.HasValue)
                return false;
            return true;
        }
        internal static HttpRange GetEncryptedBlobRange(HttpRange originalRange, string rawEncryptionData)
        {
            Argument.AssertNotNull(rawEncryptionData, "rawEncryptionData");
            EncryptionData encryptionData = EncryptionDataSerializer.Deserialize(rawEncryptionData);
            return GetEncryptedBlobRange(originalRange, encryptionData);
        }
        internal static HttpRange GetEncryptedBlobRange(HttpRange originalRange, EncryptionData encryptionData)
        {
            if (encryptionData != null) {
                switch (encryptionData.EncryptionAgent.EncryptionVersion) {
                case ClientSideEncryptionVersionInternal.V1_0:
                    return GetEncryptedBlobRangeV1_0(originalRange);
                case ClientSideEncryptionVersionInternal.V2_0:
                case ClientSideEncryptionVersionInternal.V2_1:
                    return GetEncryptedBlobRangeV2_0(originalRange, encryptionData);
                default:
                    throw Errors.InvalidArgument("encryptionData");
                }
            }
            return originalRange;
        }
        private static HttpRange GetEncryptedBlobRangeV2_0(HttpRange originalRange, EncryptionData encryptionData)
        {
            int dataLength = encryptionData.EncryptedRegionInfo.DataLength;
            int num = encryptionData.EncryptedRegionInfo.NonceLength + encryptionData.EncryptedRegionInfo.DataLength + 16;
            long num2 = 0;
            long? nullable = null;
            if (originalRange.get_Offset() != 0)
                num2 = originalRange.get_Offset() / dataLength * num;
            if (originalRange.get_Length().HasValue) {
                long num3 = (originalRange.get_Offset() + originalRange.get_Length().Value - 1) / dataLength;
                nullable = (num3 + 1) * num - num2;
            }
            return new HttpRange(num2, nullable);
        }
        private static HttpRange GetEncryptedBlobRangeV1_0(HttpRange originalRange)
        {
            int num = 0;
            long? nullable = originalRange.get_Length();
            if (originalRange.get_Offset() != 0) {
                int num2;
                if ((num2 = (int)(originalRange.get_Offset() % 16)) != 0) {
                    num += num2;
                    if (nullable.HasValue)
                        nullable += num2;
                }
                if (originalRange.get_Offset() >= 16) {
                    num += 16;
                    if (nullable.HasValue)
                        nullable += 16;
                }
            }
            if (nullable.HasValue)
                nullable += (16 - (int)(nullable % 16).Value) % 16;
            return new HttpRange(originalRange.get_Offset() - num, nullable);
        }
    }
}