using System;
using System.IO;
using System.Runtime.InteropServices;
namespace System.Security.Cryptography
{
/// Defines a stream that links data streams to cryptographic transformations.
// Token: 0x020004EF RID: 1263
[ComVisible(true)]
public class CryptoStream : Stream
{
/// Initializes a new instance of the class with a target data stream, the transformation to use, and the mode of the stream.
/// The stream on which to perform the cryptographic transformation.
/// The cryptographic transformation that is to be performed on the stream.
/// One of the values.
///
/// is not readable.
///
/// is not writable.
///
/// is invalid.
// Token: 0x06002EBC RID: 11964 RVA: 0x00096114 File Offset: 0x00094314
public CryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode)
{
if (mode == CryptoStreamMode.Read && !stream.CanRead)
{
throw new ArgumentException(Locale.GetText("Can't read on stream"));
}
if (mode == CryptoStreamMode.Write && !stream.CanWrite)
{
throw new ArgumentException(Locale.GetText("Can't write on stream"));
}
this._stream = stream;
this._transform = transform;
this._mode = mode;
this._disposed = false;
if (transform != null)
{
if (mode == CryptoStreamMode.Read)
{
this._currentBlock = new byte[transform.InputBlockSize];
this._workingBlock = new byte[transform.InputBlockSize];
}
else if (mode == CryptoStreamMode.Write)
{
this._currentBlock = new byte[transform.OutputBlockSize];
this._workingBlock = new byte[transform.OutputBlockSize];
}
}
}
// Token: 0x06002EBD RID: 11965 RVA: 0x000961E4 File Offset: 0x000943E4
~CryptoStream()
{
this.Dispose(false);
}
/// Gets a value indicating whether the current is readable.
/// true if the current stream is readable; otherwise, false.
// Token: 0x17000935 RID: 2357
// (get) Token: 0x06002EBE RID: 11966 RVA: 0x00096220 File Offset: 0x00094420
public override bool CanRead
{
get
{
return this._mode == CryptoStreamMode.Read;
}
}
/// Gets a value indicating whether you can seek within the current .
/// Always false.
// Token: 0x17000936 RID: 2358
// (get) Token: 0x06002EBF RID: 11967 RVA: 0x0009622C File Offset: 0x0009442C
public override bool CanSeek
{
get
{
return false;
}
}
/// Gets a value indicating whether the current is writable.
/// true if the current stream is writable; otherwise, false.
// Token: 0x17000937 RID: 2359
// (get) Token: 0x06002EC0 RID: 11968 RVA: 0x00096230 File Offset: 0x00094430
public override bool CanWrite
{
get
{
return this._mode == CryptoStreamMode.Write;
}
}
/// Gets the length in bytes of the stream.
/// This property is not supported.
/// This property is not supported.
// Token: 0x17000938 RID: 2360
// (get) Token: 0x06002EC1 RID: 11969 RVA: 0x0009623C File Offset: 0x0009443C
public override long Length
{
get
{
throw new NotSupportedException("Length");
}
}
/// Gets or sets the position within the current stream.
/// This property is not supported.
/// This property is not supported.
// Token: 0x17000939 RID: 2361
// (get) Token: 0x06002EC2 RID: 11970 RVA: 0x00096248 File Offset: 0x00094448
// (set) Token: 0x06002EC3 RID: 11971 RVA: 0x00096254 File Offset: 0x00094454
public override long Position
{
get
{
throw new NotSupportedException("Position");
}
set
{
throw new NotSupportedException("Position");
}
}
/// Releases all resources used by the .
// Token: 0x06002EC4 RID: 11972 RVA: 0x00096260 File Offset: 0x00094460
public void Clear()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
/// Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.
/// The current stream is not writable.
// Token: 0x06002EC5 RID: 11973 RVA: 0x00096270 File Offset: 0x00094470
public override void Close()
{
if (!this._flushedFinalBlock && this._mode == CryptoStreamMode.Write)
{
this.FlushFinalBlock();
}
if (this._stream != null)
{
this._stream.Close();
}
}
/// Reads a sequence of bytes from the current and advances the position within the stream by the number of bytes read.
/// The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero if the end of the stream has been reached.
/// An array of bytes. A maximum of bytes are read from the current stream and stored in .
/// The byte offset in at which to begin storing the data read from the current stream.
/// The maximum number of bytes to be read from the current stream.
/// The associated with current object does not match the underlying stream. For example, this exception is thrown when using with an underlying stream that is write only.
/// The parameter is less than zero.-or- The parameter is less than zero.
/// Thesum of the and parameters is longer than the length of the buffer.
// Token: 0x06002EC6 RID: 11974 RVA: 0x000962A8 File Offset: 0x000944A8
public override int Read([In] [Out] byte[] buffer, int offset, int count)
{
if (this._mode != CryptoStreamMode.Read)
{
throw new NotSupportedException(Locale.GetText("not in Read mode"));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException("offset", Locale.GetText("negative"));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", Locale.GetText("negative"));
}
if (offset > buffer.Length - count)
{
throw new ArgumentException("(offset+count)", Locale.GetText("buffer overflow"));
}
if (this._workingBlock == null)
{
return 0;
}
int num = 0;
if (count == 0 || (this._transformedPos == this._transformedCount && this._endOfStream))
{
return num;
}
if (this._waitingBlock == null)
{
this._transformedBlock = new byte[this._transform.OutputBlockSize << 2];
this._transformedPos = 0;
this._transformedCount = 0;
this._waitingBlock = new byte[this._transform.InputBlockSize];
this._waitingCount = this._stream.Read(this._waitingBlock, 0, this._waitingBlock.Length);
}
while (count > 0)
{
int num2 = this._transformedCount - this._transformedPos;
if (num2 < this._transform.InputBlockSize)
{
int num3 = 0;
this._workingCount = this._stream.Read(this._workingBlock, 0, this._transform.InputBlockSize);
this._endOfStream = this._workingCount < this._transform.InputBlockSize;
if (!this._endOfStream)
{
num3 = this._transform.TransformBlock(this._waitingBlock, 0, this._waitingBlock.Length, this._transformedBlock, this._transformedCount);
Buffer.BlockCopy(this._workingBlock, 0, this._waitingBlock, 0, this._workingCount);
this._waitingCount = this._workingCount;
}
else
{
if (this._workingCount > 0)
{
num3 = this._transform.TransformBlock(this._waitingBlock, 0, this._waitingBlock.Length, this._transformedBlock, this._transformedCount);
Buffer.BlockCopy(this._workingBlock, 0, this._waitingBlock, 0, this._workingCount);
this._waitingCount = this._workingCount;
num2 += num3;
this._transformedCount += num3;
}
if (!this._flushedFinalBlock)
{
byte[] array = this._transform.TransformFinalBlock(this._waitingBlock, 0, this._waitingCount);
num3 = array.Length;
Buffer.BlockCopy(array, 0, this._transformedBlock, this._transformedCount, array.Length);
Array.Clear(array, 0, array.Length);
this._flushedFinalBlock = true;
}
}
num2 += num3;
this._transformedCount += num3;
}
if (this._transformedPos > this._transform.OutputBlockSize)
{
Buffer.BlockCopy(this._transformedBlock, this._transformedPos, this._transformedBlock, 0, num2);
this._transformedCount -= this._transformedPos;
this._transformedPos = 0;
}
num2 = ((count >= num2) ? num2 : count);
if (num2 > 0)
{
Buffer.BlockCopy(this._transformedBlock, this._transformedPos, buffer, offset, num2);
this._transformedPos += num2;
num += num2;
offset += num2;
count -= num2;
}
if ((num2 != this._transform.InputBlockSize && this._waitingCount != this._transform.InputBlockSize) || this._endOfStream)
{
count = 0;
}
}
return num;
}
/// Writes a sequence of bytes to the current and advances the current position within this stream by the number of bytes written.
/// An array of bytes. This method copies bytes from to the current stream.
/// The byte offset in at which to begin copying bytes to the current stream.
/// The number of bytes to be written to the current stream.
/// The associated with current object does not match the underlying stream. For example, this exception is thrown when using with an underlying stream that is read only.
/// The parameter is less than zero.-or- The parameter is less than zero.
/// The sum of the and parameters is longer than the length of the buffer.
// Token: 0x06002EC7 RID: 11975 RVA: 0x00096618 File Offset: 0x00094818
public override void Write(byte[] buffer, int offset, int count)
{
if (this._mode != CryptoStreamMode.Write)
{
throw new NotSupportedException(Locale.GetText("not in Write mode"));
}
if (offset < 0)
{
throw new ArgumentOutOfRangeException("offset", Locale.GetText("negative"));
}
if (count < 0)
{
throw new ArgumentOutOfRangeException("count", Locale.GetText("negative"));
}
if (offset > buffer.Length - count)
{
throw new ArgumentException("(offset+count)", Locale.GetText("buffer overflow"));
}
if (this._stream == null)
{
throw new ArgumentNullException("inner stream was diposed");
}
int num = count;
if (this._partialCount > 0 && this._partialCount != this._transform.InputBlockSize)
{
int num2 = this._transform.InputBlockSize - this._partialCount;
num2 = ((count >= num2) ? num2 : count);
Buffer.BlockCopy(buffer, offset, this._workingBlock, this._partialCount, num2);
this._partialCount += num2;
offset += num2;
count -= num2;
}
int num3 = offset;
while (count > 0)
{
if (this._partialCount == this._transform.InputBlockSize)
{
int num4 = this._transform.TransformBlock(this._workingBlock, 0, this._partialCount, this._currentBlock, 0);
this._stream.Write(this._currentBlock, 0, num4);
this._partialCount = 0;
}
if (this._transform.CanTransformMultipleBlocks)
{
int num5 = count & ~(this._transform.InputBlockSize - 1);
int num6 = count & (this._transform.InputBlockSize - 1);
int num7 = (1 + num5 / this._transform.InputBlockSize) * this._transform.OutputBlockSize;
if (this._workingBlock.Length < num7)
{
Array.Clear(this._workingBlock, 0, this._workingBlock.Length);
this._workingBlock = new byte[num7];
}
if (num5 > 0)
{
int num8 = this._transform.TransformBlock(buffer, offset, num5, this._workingBlock, 0);
this._stream.Write(this._workingBlock, 0, num8);
}
if (num6 > 0)
{
Buffer.BlockCopy(buffer, num - num6, this._workingBlock, 0, num6);
}
this._partialCount = num6;
count = 0;
}
else
{
int num9 = Math.Min(this._transform.InputBlockSize - this._partialCount, count);
Buffer.BlockCopy(buffer, num3, this._workingBlock, this._partialCount, num9);
num3 += num9;
this._partialCount += num9;
count -= num9;
}
}
}
/// Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
// Token: 0x06002EC8 RID: 11976 RVA: 0x000968A8 File Offset: 0x00094AA8
public override void Flush()
{
if (this._stream != null)
{
this._stream.Flush();
}
}
/// Updates the underlying data source or repository with the current state of the buffer, then clears the buffer.
/// The key is corrupt which can cause invalid padding to the stream.
/// The current stream is not writable.-or- The final block has already been transformed.
// Token: 0x06002EC9 RID: 11977 RVA: 0x000968C0 File Offset: 0x00094AC0
public void FlushFinalBlock()
{
if (this._flushedFinalBlock)
{
throw new NotSupportedException(Locale.GetText("This method cannot be called twice."));
}
if (this._disposed)
{
throw new NotSupportedException(Locale.GetText("CryptoStream was disposed."));
}
if (this._mode != CryptoStreamMode.Write)
{
return;
}
this._flushedFinalBlock = true;
byte[] array = this._transform.TransformFinalBlock(this._workingBlock, 0, this._partialCount);
if (this._stream != null)
{
this._stream.Write(array, 0, array.Length);
if (this._stream is CryptoStream)
{
(this._stream as CryptoStream).FlushFinalBlock();
}
this._stream.Flush();
}
Array.Clear(array, 0, array.Length);
}
/// Sets the position within the current stream.
/// This method is not supported.
/// A byte offset relative to the parameter.
/// A object indicating the reference point used to obtain the new position.
/// This method is not supported.
// Token: 0x06002ECA RID: 11978 RVA: 0x00096980 File Offset: 0x00094B80
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException("Seek");
}
/// Sets the length of the current stream.
/// The desired length of the current stream in bytes.
/// This property exists only to support inheritance from , and cannot be used.
// Token: 0x06002ECB RID: 11979 RVA: 0x0009698C File Offset: 0x00094B8C
public override void SetLength(long value)
{
throw new NotSupportedException("SetLength");
}
/// Releases the unmanaged resources used by the and optionally releases the managed resources.
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
// Token: 0x06002ECC RID: 11980 RVA: 0x00096998 File Offset: 0x00094B98
protected override void Dispose(bool disposing)
{
if (!this._disposed)
{
this._disposed = true;
if (this._workingBlock != null)
{
Array.Clear(this._workingBlock, 0, this._workingBlock.Length);
}
if (this._currentBlock != null)
{
Array.Clear(this._currentBlock, 0, this._currentBlock.Length);
}
if (disposing)
{
this._stream = null;
this._workingBlock = null;
this._currentBlock = null;
}
}
}
// Token: 0x04001302 RID: 4866
private Stream _stream;
// Token: 0x04001303 RID: 4867
private ICryptoTransform _transform;
// Token: 0x04001304 RID: 4868
private CryptoStreamMode _mode;
// Token: 0x04001305 RID: 4869
private byte[] _currentBlock;
// Token: 0x04001306 RID: 4870
private bool _disposed;
// Token: 0x04001307 RID: 4871
private bool _flushedFinalBlock;
// Token: 0x04001308 RID: 4872
private int _partialCount;
// Token: 0x04001309 RID: 4873
private bool _endOfStream;
// Token: 0x0400130A RID: 4874
private byte[] _waitingBlock;
// Token: 0x0400130B RID: 4875
private int _waitingCount;
// Token: 0x0400130C RID: 4876
private byte[] _transformedBlock;
// Token: 0x0400130D RID: 4877
private int _transformedPos;
// Token: 0x0400130E RID: 4878
private int _transformedCount;
// Token: 0x0400130F RID: 4879
private byte[] _workingBlock;
// Token: 0x04001310 RID: 4880
private int _workingCount;
}
}