using System; using System.Security.Cryptography; namespace ScreenConnect; public abstract class BlockBufferStream : BufferStreamBase { private class IdentityTransform : ICryptoTransform, IDisposable { public static readonly IdentityTransform Instance = new IdentityTransform(); public int InputBlockSize => 1; public int OutputBlockSize => 1; public bool CanTransformMultipleBlocks => true; public bool CanReuseTransform => true; public void Dispose() { } public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset) { int num = Math.Min(inputCount, outputBuffer.Length - outputOffset); Buffer.BlockCopy(inputBuffer, inputOffset, outputBuffer, outputOffset, num); return num; } public byte[] TransformFinalBlock(byte[] inputBuffer, int inputOffset, int inputCount) { throw new NotSupportedException(); } } private ICryptoTransform transform; protected ICryptoTransform Transform => transform; protected int BlockSize => transform.InputBlockSize; public bool IsSecureChannel => !(transform is IdentityTransform); public BlockBufferStream() { transform = IdentityTransform.Instance; OnBlockSizeChanged(); } protected abstract void OnBlockSizeChanged(); protected abstract ICryptoTransform CreateTransform(byte[] key, byte[] iv); protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing) { transform.Dispose(); } } protected void ChangeTransform(ICryptoTransform transform) { int inputBlockSize = this.transform.InputBlockSize; this.transform = transform; if (this.transform.InputBlockSize != inputBlockSize) { OnBlockSizeChanged(); } } public virtual void StartSecureChannel(byte[] key, byte[] iv) { ChangeTransform(CreateTransform(key, iv)); } }