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, pulledOutIV : false, 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.DecryptInternal( content, encryptionData, ivInStream, CanIgnorePadding(contentRange), async, cancellationToken).ConfigureAwait(false); return(await TrimStreamInternal(plaintext, originalRange, contentRange, ivInStream, async, cancellationToken).ConfigureAwait(false)); }
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)); }