123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- #if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
- #pragma warning disable
- using System;
- #if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- using System.Buffers;
- #endif
- using System.Diagnostics;
- using System.IO;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities;
- using Best.HTTP.SecureProtocol.Org.BouncyCastle.Utilities.IO;
- namespace Best.HTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO
- {
- public sealed class CipherStream
- : Stream
- {
- private readonly Stream m_stream;
- private readonly IBufferedCipher m_readCipher, m_writeCipher;
- private byte[] m_readBuf;
- private int m_readBufPos;
- private bool m_readEnded;
- public CipherStream(Stream stream, IBufferedCipher readCipher, IBufferedCipher writeCipher)
- {
- m_stream = stream;
- if (readCipher != null)
- {
- m_readCipher = readCipher;
- m_readBuf = null;
- }
- if (writeCipher != null)
- {
- m_writeCipher = writeCipher;
- }
- }
- public IBufferedCipher ReadCipher => m_readCipher;
- public IBufferedCipher WriteCipher => m_writeCipher;
- public override bool CanRead
- {
- get { return m_stream.CanRead; }
- }
- public sealed override bool CanSeek
- {
- get { return false; }
- }
- public override bool CanWrite
- {
- get { return m_stream.CanWrite; }
- }
- #if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || (UNITY_2021_2_OR_NEWER && (NET_STANDARD_2_0 || NET_STANDARD_2_1))
- public override void CopyTo(Stream destination, int bufferSize)
- {
- if (m_readCipher == null)
- {
- m_stream.CopyTo(destination, bufferSize);
- }
- else
- {
- base.CopyTo(destination, bufferSize);
- }
- }
- #endif
- public override void Flush()
- {
- m_stream.Flush();
- }
- public sealed override long Length
- {
- get { throw new NotSupportedException(); }
- }
- public sealed override long Position
- {
- get { throw new NotSupportedException(); }
- set { throw new NotSupportedException(); }
- }
- public override int Read(byte[] buffer, int offset, int count)
- {
- if (m_readCipher == null)
- return m_stream.Read(buffer, offset, count);
- Streams.ValidateBufferArguments(buffer, offset, count);
- int num = 0;
- while (num < count)
- {
- if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
- {
- if (!FillInBuf())
- break;
- }
- int numToCopy = System.Math.Min(count - num, m_readBuf.Length - m_readBufPos);
- Array.Copy(m_readBuf, m_readBufPos, buffer, offset + num, numToCopy);
- m_readBufPos += numToCopy;
- num += numToCopy;
- }
- return num;
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- public override int Read(Span<byte> buffer)
- {
- if (buffer.IsEmpty)
- return 0;
- if (m_readCipher == null)
- return m_stream.Read(buffer);
- int num = 0;
- while (num < buffer.Length)
- {
- if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
- {
- if (!FillInBuf())
- break;
- }
- int numToCopy = System.Math.Min(buffer.Length - num, m_readBuf.Length - m_readBufPos);
- m_readBuf.AsSpan(m_readBufPos, numToCopy).CopyTo(buffer[num..]);
- m_readBufPos += numToCopy;
- num += numToCopy;
- }
- return num;
- }
- #endif
- public override int ReadByte()
- {
- if (m_readCipher == null)
- return m_stream.ReadByte();
- if (m_readBuf == null || m_readBufPos >= m_readBuf.Length)
- {
- if (!FillInBuf())
- return -1;
- }
- return m_readBuf[m_readBufPos++];
- }
- public sealed override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotSupportedException();
- }
- public sealed override void SetLength(long length)
- {
- throw new NotSupportedException();
- }
- public override void Write(byte[] buffer, int offset, int count)
- {
- if (m_writeCipher == null)
- {
- m_stream.Write(buffer, offset, count);
- return;
- }
- Streams.ValidateBufferArguments(buffer, offset, count);
- if (count > 0)
- {
- #if NETCOREAPP1_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- int outputSize = m_writeCipher.GetUpdateOutputSize(count);
- byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null;
- try
- {
- int length = m_writeCipher.ProcessBytes(buffer, offset, count, output, 0);
- if (length > 0)
- {
- m_stream.Write(output, 0, length);
- }
- }
- finally
- {
- if (output != null)
- {
- ArrayPool<byte>.Shared.Return(output);
- }
- }
- #else
- byte[] output = m_writeCipher.ProcessBytes(buffer, offset, count);
- if (output != null)
- {
- m_stream.Write(output, 0, output.Length);
- }
- #endif
- }
- }
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- public override void Write(ReadOnlySpan<byte> buffer)
- {
- if (buffer.IsEmpty)
- return;
- if (m_writeCipher == null)
- {
- m_stream.Write(buffer);
- return;
- }
- int outputSize = m_writeCipher.GetUpdateOutputSize(buffer.Length);
- byte[] output = outputSize > 0 ? ArrayPool<byte>.Shared.Rent(outputSize) : null;
- try
- {
- int length = m_writeCipher.ProcessBytes(buffer, Spans.FromNullable(output));
- if (length > 0)
- {
- m_stream.Write(output[..length]);
- }
- }
- finally
- {
- if (output != null)
- {
- ArrayPool<byte>.Shared.Return(output);
- }
- }
- }
- #endif
- public override void WriteByte(byte value)
- {
- if (m_writeCipher == null)
- {
- m_stream.WriteByte(value);
- return;
- }
- byte[] data = m_writeCipher.ProcessByte(value);
- if (data != null)
- {
- m_stream.Write(data, 0, data.Length);
- }
- }
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (m_writeCipher != null)
- {
- #if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER || UNITY_2021_2_OR_NEWER
- int outputSize = m_writeCipher.GetOutputSize(0);
- Span<byte> output = outputSize <= 256
- ? stackalloc byte[outputSize]
- : new byte[outputSize];
- int len = m_writeCipher.DoFinal(output);
- m_stream.Write(output[..len]);
- #else
- byte[] data = m_writeCipher.DoFinal();
- m_stream.Write(data, 0, data.Length);
- #endif
- }
- m_stream.Dispose();
- }
- base.Dispose(disposing);
- }
- private bool FillInBuf()
- {
- if (m_readEnded)
- return false;
- m_readBufPos = 0;
- do
- {
- m_readBuf = ReadAndProcessBlock();
- }
- while (!m_readEnded && m_readBuf == null);
- return m_readBuf != null;
- }
- private byte[] ReadAndProcessBlock()
- {
- int blockSize = m_readCipher.GetBlockSize();
- int readSize = blockSize == 0 ? 256 : blockSize;
- byte[] block = new byte[readSize];
- int numRead = 0;
- do
- {
- int count = m_stream.Read(block, numRead, block.Length - numRead);
- if (count < 1)
- {
- m_readEnded = true;
- break;
- }
- numRead += count;
- }
- while (numRead < block.Length);
- Debug.Assert(m_readEnded || numRead == block.Length);
- byte[] bytes = m_readEnded
- ? m_readCipher.DoFinal(block, 0, numRead)
- : m_readCipher.ProcessBytes(block);
- if (bytes != null && bytes.Length == 0)
- {
- bytes = null;
- }
- return bytes;
- }
- }
- }
- #pragma warning restore
- #endif
|