466 lines
18 KiB
C#
466 lines
18 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace System.Security.Cryptography
|
|
{
|
|
/// <summary>Defines a stream that links data streams to cryptographic transformations.</summary>
|
|
// Token: 0x020004EF RID: 1263
|
|
[ComVisible(true)]
|
|
public class CryptoStream : Stream
|
|
{
|
|
/// <summary>Initializes a new instance of the <see cref="T:System.Security.Cryptography.CryptoStream" /> class with a target data stream, the transformation to use, and the mode of the stream.</summary>
|
|
/// <param name="stream">The stream on which to perform the cryptographic transformation. </param>
|
|
/// <param name="transform">The cryptographic transformation that is to be performed on the stream. </param>
|
|
/// <param name="mode">One of the <see cref="T:System.Security.Cryptography.CryptoStreamMode" /> values. </param>
|
|
/// <exception cref="T:System.ArgumentException">
|
|
/// <paramref name="stream" /> is not readable.</exception>
|
|
/// <exception cref="T:System.ArgumentException">
|
|
/// <paramref name="stream" /> is not writable.</exception>
|
|
/// <exception cref="T:System.ArgumentException">
|
|
/// <paramref name="stream" /> is invalid.</exception>
|
|
// 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);
|
|
}
|
|
|
|
/// <summary>Gets a value indicating whether the current <see cref="T:System.Security.Cryptography.CryptoStream" /> is readable.</summary>
|
|
/// <returns>true if the current stream is readable; otherwise, false.</returns>
|
|
// Token: 0x17000935 RID: 2357
|
|
// (get) Token: 0x06002EBE RID: 11966 RVA: 0x00096220 File Offset: 0x00094420
|
|
public override bool CanRead
|
|
{
|
|
get
|
|
{
|
|
return this._mode == CryptoStreamMode.Read;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets a value indicating whether you can seek within the current <see cref="T:System.Security.Cryptography.CryptoStream" />.</summary>
|
|
/// <returns>Always false.</returns>
|
|
// Token: 0x17000936 RID: 2358
|
|
// (get) Token: 0x06002EBF RID: 11967 RVA: 0x0009622C File Offset: 0x0009442C
|
|
public override bool CanSeek
|
|
{
|
|
get
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets a value indicating whether the current <see cref="T:System.Security.Cryptography.CryptoStream" /> is writable.</summary>
|
|
/// <returns>true if the current stream is writable; otherwise, false.</returns>
|
|
// Token: 0x17000937 RID: 2359
|
|
// (get) Token: 0x06002EC0 RID: 11968 RVA: 0x00096230 File Offset: 0x00094430
|
|
public override bool CanWrite
|
|
{
|
|
get
|
|
{
|
|
return this._mode == CryptoStreamMode.Write;
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets the length in bytes of the stream.</summary>
|
|
/// <returns>This property is not supported.</returns>
|
|
/// <exception cref="T:System.NotSupportedException">This property is not supported. </exception>
|
|
// Token: 0x17000938 RID: 2360
|
|
// (get) Token: 0x06002EC1 RID: 11969 RVA: 0x0009623C File Offset: 0x0009443C
|
|
public override long Length
|
|
{
|
|
get
|
|
{
|
|
throw new NotSupportedException("Length");
|
|
}
|
|
}
|
|
|
|
/// <summary>Gets or sets the position within the current stream.</summary>
|
|
/// <returns>This property is not supported.</returns>
|
|
/// <exception cref="T:System.NotSupportedException">This property is not supported. </exception>
|
|
// 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");
|
|
}
|
|
}
|
|
|
|
/// <summary>Releases all resources used by the <see cref="T:System.Security.Cryptography.CryptoStream" />.</summary>
|
|
// Token: 0x06002EC4 RID: 11972 RVA: 0x00096260 File Offset: 0x00094460
|
|
public void Clear()
|
|
{
|
|
this.Dispose(true);
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
|
|
/// <summary>Closes the current stream and releases any resources (such as sockets and file handles) associated with the current stream.</summary>
|
|
/// <exception cref="T:System.NotSupportedException">The current stream is not writable. </exception>
|
|
// 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();
|
|
}
|
|
}
|
|
|
|
/// <summary>Reads a sequence of bytes from the current <see cref="T:System.Security.Cryptography.CryptoStream" /> and advances the position within the stream by the number of bytes read.</summary>
|
|
/// <returns>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.</returns>
|
|
/// <param name="buffer">An array of bytes. A maximum of <paramref name="count" /> bytes are read from the current stream and stored in <paramref name="buffer" />. </param>
|
|
/// <param name="offset">The byte offset in <paramref name="buffer" /> at which to begin storing the data read from the current stream. </param>
|
|
/// <param name="count">The maximum number of bytes to be read from the current stream. </param>
|
|
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Security.Cryptography.CryptoStreamMode" /> associated with current <see cref="T:System.Security.Cryptography.CryptoStream" /> object does not match the underlying stream. For example, this exception is thrown when using <see cref="F:System.Security.Cryptography.CryptoStreamMode.Read" /> with an underlying stream that is write only. </exception>
|
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="offset" /> parameter is less than zero.-or- The <paramref name="count" /> parameter is less than zero. </exception>
|
|
/// <exception cref="T:System.ArgumentException">Thesum of the <paramref name="count" /> and <paramref name="offset" /> parameters is longer than the length of the buffer. </exception>
|
|
// 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;
|
|
}
|
|
|
|
/// <summary>Writes a sequence of bytes to the current <see cref="T:System.Security.Cryptography.CryptoStream" /> and advances the current position within this stream by the number of bytes written.</summary>
|
|
/// <param name="buffer">An array of bytes. This method copies <paramref name="count" /> bytes from <paramref name="buffer" /> to the current stream. </param>
|
|
/// <param name="offset">The byte offset in <paramref name="buffer" /> at which to begin copying bytes to the current stream. </param>
|
|
/// <param name="count">The number of bytes to be written to the current stream. </param>
|
|
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Security.Cryptography.CryptoStreamMode" /> associated with current <see cref="T:System.Security.Cryptography.CryptoStream" /> object does not match the underlying stream. For example, this exception is thrown when using <see cref="F:System.Security.Cryptography.CryptoStreamMode.Write" /> with an underlying stream that is read only. </exception>
|
|
/// <exception cref="T:System.ArgumentOutOfRangeException">The <paramref name="offset" /> parameter is less than zero.-or- The <paramref name="count" /> parameter is less than zero. </exception>
|
|
/// <exception cref="T:System.ArgumentException">The sum of the <paramref name="count" /> and <paramref name="offset" /> parameters is longer than the length of the buffer. </exception>
|
|
// 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>Clears all buffers for this stream and causes any buffered data to be written to the underlying device.</summary>
|
|
// Token: 0x06002EC8 RID: 11976 RVA: 0x000968A8 File Offset: 0x00094AA8
|
|
public override void Flush()
|
|
{
|
|
if (this._stream != null)
|
|
{
|
|
this._stream.Flush();
|
|
}
|
|
}
|
|
|
|
/// <summary>Updates the underlying data source or repository with the current state of the buffer, then clears the buffer.</summary>
|
|
/// <exception cref="T:System.Security.Cryptography.CryptographicException">The key is corrupt which can cause invalid padding to the stream. </exception>
|
|
/// <exception cref="T:System.NotSupportedException">The current stream is not writable.-or- The final block has already been transformed. </exception>
|
|
// 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);
|
|
}
|
|
|
|
/// <summary>Sets the position within the current stream.</summary>
|
|
/// <returns>This method is not supported.</returns>
|
|
/// <param name="offset">A byte offset relative to the <paramref name="origin" /> parameter. </param>
|
|
/// <param name="origin">A <see cref="T:System.IO.SeekOrigin" /> object indicating the reference point used to obtain the new position. </param>
|
|
/// <exception cref="T:System.NotSupportedException">This method is not supported. </exception>
|
|
// Token: 0x06002ECA RID: 11978 RVA: 0x00096980 File Offset: 0x00094B80
|
|
public override long Seek(long offset, SeekOrigin origin)
|
|
{
|
|
throw new NotSupportedException("Seek");
|
|
}
|
|
|
|
/// <summary>Sets the length of the current stream.</summary>
|
|
/// <param name="value">The desired length of the current stream in bytes. </param>
|
|
/// <exception cref="T:System.NotSupportedException">This property exists only to support inheritance from <see cref="T:System.IO.Stream" />, and cannot be used.</exception>
|
|
// Token: 0x06002ECB RID: 11979 RVA: 0x0009698C File Offset: 0x00094B8C
|
|
public override void SetLength(long value)
|
|
{
|
|
throw new NotSupportedException("SetLength");
|
|
}
|
|
|
|
/// <summary>Releases the unmanaged resources used by the <see cref="T:System.Security.Cryptography.CryptoStream" /> and optionally releases the managed resources.</summary>
|
|
/// <param name="disposing">true to release both managed and unmanaged resources; false to release only unmanaged resources. </param>
|
|
// 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;
|
|
}
|
|
}
|