public override void Write(byte[] buffer, int offset, int count) { // Keep buffering until we have 16 bytes of IV. if (this.bufferIV && this.position < 16) { int bytesToCopy = 16 - (int)this.position; bytesToCopy = count > bytesToCopy ? bytesToCopy : count; Array.Copy(buffer, offset, this.iv, (int)this.position, bytesToCopy); this.position += bytesToCopy; offset += bytesToCopy; count -= bytesToCopy; if (this.position < 16) { return; } } // Wrap user stream with LengthLimitingStream. This stream will be used to discard the extra bytes we downloaded in order to deal with AES block size. // Create crypto stream around the length limiting stream once per download and start writing to it. During retries, the state is maintained and // new crypto streams will not be created each time. if (this.cryptoStream == null) { LengthLimitingStream lengthLimitingStream = new LengthLimitingStream(this.userStream, this.discardFirst, this.userProvidedLength); this.cryptoStream = this.encryptionPolicy.DecryptBlob(lengthLimitingStream, this.metadata, out this.transform, this.requireEncryption, iv: !this.bufferIV ? null : this.iv, noPadding: this.noPadding); } // Route the remaining data through the crypto stream. if (count > 0) { this.cryptoStream.Write(buffer, offset, count); this.position += count; } }
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state) { StorageAsyncResult <NullType> storageAsyncResult = new StorageAsyncResult <NullType>(callback, state); // Keep buffering until we have 16 bytes of IV. if (this.bufferIV && this.position < 16) { int bytesToCopy = 16 - (int)this.position; bytesToCopy = count > bytesToCopy ? bytesToCopy : count; Array.Copy(buffer, offset, this.iv, (int)this.position, bytesToCopy); this.position += bytesToCopy; offset += bytesToCopy; count -= bytesToCopy; if (this.position < 16) { storageAsyncResult.OnComplete(); return(storageAsyncResult); } } // Wrap user stream with LengthLimitingStream. This stream will be used to discard the extra bytes we downloaded in order to deal with AES block size. // Create crypto stream around the length limiting stream once per download and start writing to it. During retries, the state is maintained and // new crypto streams will not be created each time. if (this.cryptoStream == null) { LengthLimitingStream lengthLimitingStream = new LengthLimitingStream(this.userStream, this.discardFirst, this.userProvidedLength); this.cryptoStream = this.encryptionPolicy.DecryptBlob(lengthLimitingStream, this.metadata, out this.transform, this.requireEncryption, iv: !this.bufferIV ? null : this.iv, noPadding: this.noPadding); } if (count <= 0) { storageAsyncResult.OnComplete(); } else { // Route the remaining data through the crypto stream. storageAsyncResult.OperationState = count; this.cryptoStream.BeginWrite(buffer, offset, count, this.WriteStreamCallback, storageAsyncResult); } return(storageAsyncResult); }