Files
2026-06-04 11:42:34 +02:00

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;
}
}