mirror of
https://github.com/MCCTeam/Minecraft-Console-Client
synced 2025-10-14 21:22:49 +00:00
Mono Framework does not handle CFB-8 AES encryption mode. So now MCC will now use borrowed code from the BouncyCastle project for handling AES when running on Mono framework, instead of using a dirty workaround to try getting Mono encryption working. Regular .NET framework encryption module will still be used when not running under Mono (eg on Windows or using Wine) Should hopefully fix all the issues encountered on Mono including #41 and finally achieve full compatibility of MCC with Mac and Linux.
234 lines
4.5 KiB
C#
234 lines
4.5 KiB
C#
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
|
|
using Org.BouncyCastle.Crypto;
|
|
|
|
namespace 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(); }
|
|
}
|
|
|
|
public override void Close()
|
|
{
|
|
if (outCipher != null)
|
|
{
|
|
byte[] data = outCipher.DoFinal();
|
|
stream.Write(data, 0, data.Length);
|
|
stream.Flush();
|
|
}
|
|
stream.Close();
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|