Beispiel #1
0
        private async Task <BinaryData> ClientSideDecryptInternal(BinaryData downloadedMessage, bool async, CancellationToken cancellationToken)
        {
            if (!EncryptedMessageSerializer.TryDeserialize(downloadedMessage, out var encryptedMessage))
            {
                return(downloadedMessage); // not recognized as client-side encrypted message
            }

            var encryptedMessageStream = new MemoryStream(Convert.FromBase64String(encryptedMessage.EncryptedMessageText));
            var decryptedMessageStream = await _decryptor.DecryptReadInternal(
                encryptedMessageStream,
                encryptedMessage.EncryptionData,
                ivInStream : false,
                noPadding : false,
                async : async,
                cancellationToken).ConfigureAwait(false);

            // if we got back the stream we put in, then we couldn't decrypt and are supposed to return the original
            // message to the user
            if (encryptedMessageStream == decryptedMessageStream)
            {
                return(downloadedMessage);
            }

            return(async ?
                   await BinaryData.FromStreamAsync(decryptedMessageStream, cancellationToken).ConfigureAwait(false) :
                   BinaryData.FromStream(decryptedMessageStream));
        }
Beispiel #2
0
        public async Task <Stream> DecryptInternal(
            Stream content,
            Metadata metadata,
            HttpRange originalRange,
            string receivedContentRange,
            bool async,
            CancellationToken cancellationToken)
        {
            ContentRange?contentRange = string.IsNullOrWhiteSpace(receivedContentRange)
                ? default
                : ContentRange.Parse(receivedContentRange);

            EncryptionData encryptionData = GetAndValidateEncryptionDataOrDefault(metadata);

            if (encryptionData == default)
            {
                return(await TrimStreamInternal(content, originalRange, contentRange, alreadyTrimmedOffsetAmount : 0, async, cancellationToken).ConfigureAwait(false));
            }

            bool ivInStream = originalRange.Offset >= Constants.ClientSideEncryption.EncryptionBlockSize;

            // this method throws when key cannot be resolved. Blobs is intended to throw on this failure.
            var plaintext = await _decryptor.DecryptReadInternal(
                content,
                encryptionData,
                ivInStream,
                CanIgnorePadding(contentRange),
                async,
                cancellationToken).ConfigureAwait(false);

            int v2StartRegion0Indexed = (int)((contentRange?.Start / encryptionData.EncryptedRegionInfo?.GetTotalRegionLength()) ?? 0);
            int alreadyTrimmedOffset  = encryptionData.EncryptionAgent.EncryptionVersion switch
            {
                ClientSideEncryptionVersion.V1_0 => ivInStream ? Constants.ClientSideEncryption.EncryptionBlockSize : 0,
                // first block is special case where we don't want to communicate a trim. Otherwise communicate nonce length * 1-indexed start region + tag length * 0-indexed region
                ClientSideEncryptionVersion.V2_0 => contentRange?.Start > 0
                    ? (-encryptionData.EncryptedRegionInfo.NonceLength * (v2StartRegion0Indexed)) - (Constants.ClientSideEncryption.V2.TagSize * v2StartRegion0Indexed)
                    : 0,
                _ => throw Errors.ClientSideEncryption.ClientSideEncryptionVersionNotSupported()
            };

            return(await TrimStreamInternal(plaintext, originalRange, contentRange, alreadyTrimmedOffset, async, cancellationToken).ConfigureAwait(false));
        }