private async Task FlushFinalBlockAsync(bool useAsync) { if (_finalBlockTransformed) { throw new NotSupportedException(SR.Cryptography_CryptoStream_FlushFinalBlockTwice); } _finalBlockTransformed = true; // Transform and write out the final bytes. if (_canWrite) { Debug.Assert(_outputBufferIndex == 0, "The output index can only ever be non-zero when in read mode."); byte[] finalBytes = _transform.TransformFinalBlock(_inputBuffer, 0, _inputBufferIndex); if (useAsync) { await _stream.WriteAsync(new ReadOnlyMemory <byte>(finalBytes)).ConfigureAwait(false); } else { _stream.Write(finalBytes, 0, finalBytes.Length); } } // If the inner stream is a CryptoStream, then we want to call FlushFinalBlock on it too, otherwise just Flush. CryptoStream innerCryptoStream = _stream as CryptoStream; if (innerCryptoStream != null) { if (!innerCryptoStream.HasFlushedFinalBlock) { await innerCryptoStream.FlushFinalBlockAsync(useAsync).ConfigureAwait(false); } } else { if (useAsync) { await _stream.FlushAsync().ConfigureAwait(false); } else { _stream.Flush(); } } // zeroize plain text material before returning if (_inputBuffer != null) { Array.Clear(_inputBuffer, 0, _inputBuffer.Length); } if (_outputBuffer != null) { Array.Clear(_outputBuffer, 0, _outputBuffer.Length); } }
private async Task FlushFinalBlockAsync(bool useAsync) { if (_finalBlockTransformed) { throw new NotSupportedException(SR.Cryptography_CryptoStream_FlushFinalBlockTwice); } // We have to process the last block here. First, we have the final block in _InputBuffer, so transform it byte[] finalBytes = _transform.TransformFinalBlock(_inputBuffer, 0, _inputBufferIndex); _finalBlockTransformed = true; // Now, write out anything sitting in the _outputBuffer... if (_canWrite && _outputBufferIndex > 0) { if (useAsync) { await _stream.WriteAsync(new ReadOnlyMemory <byte>(_outputBuffer, 0, _outputBufferIndex)).ConfigureAwait(false); } else { _stream.Write(_outputBuffer, 0, _outputBufferIndex); } _outputBufferIndex = 0; } // Write out finalBytes if (_canWrite) { if (useAsync) { await _stream.WriteAsync(new ReadOnlyMemory <byte>(finalBytes)).ConfigureAwait(false); } else { _stream.Write(finalBytes, 0, finalBytes.Length); } } // If the inner stream is a CryptoStream, then we want to call FlushFinalBlock on it too, otherwise just Flush. CryptoStream innerCryptoStream = _stream as CryptoStream; if (innerCryptoStream != null) { if (!innerCryptoStream.HasFlushedFinalBlock) { await innerCryptoStream.FlushFinalBlockAsync(useAsync).ConfigureAwait(false); } } else { if (useAsync) { await _stream.FlushAsync().ConfigureAwait(false); } else { _stream.Flush(); } } // zeroize plain text material before returning if (_inputBuffer != null) { Array.Clear(_inputBuffer, 0, _inputBuffer.Length); } if (_outputBuffer != null) { Array.Clear(_outputBuffer, 0, _outputBuffer.Length); } }