You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
257 lines
5.2 KiB
257 lines
5.2 KiB
1 year ago
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||
|
#pragma warning disable
|
||
|
using System;
|
||
|
using System.Diagnostics;
|
||
|
using System.IO;
|
||
|
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities;
|
||
|
|
||
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.IO
|
||
|
{
|
||
|
public class CipherStream
|
||
|
: Stream
|
||
|
{
|
||
|
internal Stream stream;
|
||
|
internal IBufferedCipher inCipher, outCipher;
|
||
|
private byte[] mInBuf;
|
||
|
private int mInPos;
|
||
|
private bool inStreamEnded;
|
||
|
|
||
|
public CipherStream(
|
||
|
Stream stream,
|
||
|
IBufferedCipher readCipher,
|
||
|
IBufferedCipher writeCipher)
|
||
|
{
|
||
|
this.stream = stream;
|
||
|
|
||
|
if (readCipher != null)
|
||
|
{
|
||
|
this.inCipher = readCipher;
|
||
|
mInBuf = null;
|
||
|
}
|
||
|
|
||
|
if (writeCipher != null)
|
||
|
{
|
||
|
this.outCipher = writeCipher;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public IBufferedCipher ReadCipher
|
||
|
{
|
||
|
get { return inCipher; }
|
||
|
}
|
||
|
|
||
|
public IBufferedCipher WriteCipher
|
||
|
{
|
||
|
get { return outCipher; }
|
||
|
}
|
||
|
|
||
|
public override int ReadByte()
|
||
|
{
|
||
|
if (inCipher == null)
|
||
|
return stream.ReadByte();
|
||
|
|
||
|
if (mInBuf == null || mInPos >= mInBuf.Length)
|
||
|
{
|
||
|
if (!FillInBuf())
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
return mInBuf[mInPos++];
|
||
|
}
|
||
|
|
||
|
public override int Read(
|
||
|
byte[] buffer,
|
||
|
int offset,
|
||
|
int count)
|
||
|
{
|
||
|
if (inCipher == null)
|
||
|
return stream.Read(buffer, offset, count);
|
||
|
|
||
|
int num = 0;
|
||
|
while (num < count)
|
||
|
{
|
||
|
if (mInBuf == null || mInPos >= mInBuf.Length)
|
||
|
{
|
||
|
if (!FillInBuf())
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
int numToCopy = System.Math.Min(count - num, mInBuf.Length - mInPos);
|
||
|
Array.Copy(mInBuf, mInPos, buffer, offset + num, numToCopy);
|
||
|
mInPos += numToCopy;
|
||
|
num += numToCopy;
|
||
|
}
|
||
|
|
||
|
return num;
|
||
|
}
|
||
|
|
||
|
private bool FillInBuf()
|
||
|
{
|
||
|
if (inStreamEnded)
|
||
|
return false;
|
||
|
|
||
|
mInPos = 0;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
mInBuf = ReadAndProcessBlock();
|
||
|
}
|
||
|
while (!inStreamEnded && mInBuf == null);
|
||
|
|
||
|
return mInBuf != null;
|
||
|
}
|
||
|
|
||
|
private byte[] ReadAndProcessBlock()
|
||
|
{
|
||
|
int blockSize = inCipher.GetBlockSize();
|
||
|
int readSize = (blockSize == 0) ? 256 : blockSize;
|
||
|
|
||
|
byte[] block = new byte[readSize];
|
||
|
int numRead = 0;
|
||
|
do
|
||
|
{
|
||
|
int count = stream.Read(block, numRead, block.Length - numRead);
|
||
|
if (count < 1)
|
||
|
{
|
||
|
inStreamEnded = true;
|
||
|
break;
|
||
|
}
|
||
|
numRead += count;
|
||
|
}
|
||
|
while (numRead < block.Length);
|
||
|
|
||
|
Debug.Assert(inStreamEnded || numRead == block.Length);
|
||
|
|
||
|
byte[] bytes = inStreamEnded
|
||
|
? inCipher.DoFinal(block, 0, numRead)
|
||
|
: inCipher.ProcessBytes(block);
|
||
|
|
||
|
if (bytes != null && bytes.Length == 0)
|
||
|
{
|
||
|
bytes = null;
|
||
|
}
|
||
|
|
||
|
return bytes;
|
||
|
}
|
||
|
|
||
|
public override void Write(
|
||
|
byte[] buffer,
|
||
|
int offset,
|
||
|
int count)
|
||
|
{
|
||
|
Debug.Assert(buffer != null);
|
||
|
Debug.Assert(0 <= offset && offset <= buffer.Length);
|
||
|
Debug.Assert(count >= 0);
|
||
|
|
||
|
int end = offset + count;
|
||
|
|
||
|
Debug.Assert(0 <= end && end <= buffer.Length);
|
||
|
|
||
|
if (outCipher == null)
|
||
|
{
|
||
|
stream.Write(buffer, offset, count);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
byte[] data = outCipher.ProcessBytes(buffer, offset, count);
|
||
|
if (data != null)
|
||
|
{
|
||
|
stream.Write(data, 0, data.Length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void WriteByte(
|
||
|
byte b)
|
||
|
{
|
||
|
if (outCipher == null)
|
||
|
{
|
||
|
stream.WriteByte(b);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
byte[] data = outCipher.ProcessByte(b);
|
||
|
if (data != null)
|
||
|
{
|
||
|
stream.Write(data, 0, data.Length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override bool CanRead
|
||
|
{
|
||
|
get { return stream.CanRead && (inCipher != null); }
|
||
|
}
|
||
|
|
||
|
public override bool CanWrite
|
||
|
{
|
||
|
get { return stream.CanWrite && (outCipher != null); }
|
||
|
}
|
||
|
|
||
|
public override bool CanSeek
|
||
|
{
|
||
|
get { return false; }
|
||
|
}
|
||
|
|
||
|
public sealed override long Length
|
||
|
{
|
||
|
get { throw new NotSupportedException(); }
|
||
|
}
|
||
|
|
||
|
public sealed override long Position
|
||
|
{
|
||
|
get { throw new NotSupportedException(); }
|
||
|
set { throw new NotSupportedException(); }
|
||
|
}
|
||
|
|
||
|
#if PORTABLE || NETFX_CORE
|
||
|
protected override void Dispose(bool disposing)
|
||
|
{
|
||
|
if (disposing)
|
||
|
{
|
||
|
if (outCipher != null)
|
||
|
{
|
||
|
byte[] data = outCipher.DoFinal();
|
||
|
stream.Write(data, 0, data.Length);
|
||
|
stream.Flush();
|
||
|
}
|
||
|
BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(stream);
|
||
|
}
|
||
|
base.Dispose(disposing);
|
||
|
}
|
||
|
#else
|
||
|
public override void Close()
|
||
|
{
|
||
|
if (outCipher != null)
|
||
|
{
|
||
|
byte[] data = outCipher.DoFinal();
|
||
|
stream.Write(data, 0, data.Length);
|
||
|
stream.Flush();
|
||
|
}
|
||
|
BestHTTP.SecureProtocol.Org.BouncyCastle.Utilities.Platform.Dispose(stream);
|
||
|
base.Close();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
public override void Flush()
|
||
|
{
|
||
|
// Note: outCipher.DoFinal is only called during Close()
|
||
|
stream.Flush();
|
||
|
}
|
||
|
|
||
|
public sealed override long Seek(
|
||
|
long offset,
|
||
|
SeekOrigin origin)
|
||
|
{
|
||
|
throw new NotSupportedException();
|
||
|
}
|
||
|
|
||
|
public sealed override void SetLength(
|
||
|
long length)
|
||
|
{
|
||
|
throw new NotSupportedException();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#pragma warning restore
|
||
|
#endif
|