public override Stream Receive(TimeSpan timeout, Information options)
{
if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
if (!_connect) throw new ConnectionException();
lock (_receiveLock)
{
try
{
if (_version.HasFlag(SecureConnectionVersion.Version3))
{
using (Stream stream = _connection.Receive(timeout, options))
{
byte[] totalReceiveSizeBuff = new byte[8];
if (stream.Read(totalReceiveSizeBuff, 0, totalReceiveSizeBuff.Length) != totalReceiveSizeBuff.Length) throw new ConnectionException();
long totalReceiveSize = NetworkConverter.ToInt64(totalReceiveSizeBuff);
if (_informationVersion3.HashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
{
const int hashLength = 32;
_totalReceiveSize += (stream.Length - (8 + hashLength));
if (totalReceiveSize != _totalReceiveSize) throw new ConnectionException();
byte[] otherHmacBuff = new byte[hashLength];
stream.Seek(-hashLength, SeekOrigin.End);
if (stream.Read(otherHmacBuff, 0, otherHmacBuff.Length) != otherHmacBuff.Length) throw new ConnectionException();
stream.SetLength(stream.Length - hashLength);
stream.Seek(0, SeekOrigin.Begin);
byte[] myHmacBuff = HmacSha256.ComputeHash(stream, _informationVersion3.OtherHmacKey);
if (!Unsafe.Equals(otherHmacBuff, myHmacBuff)) throw new ConnectionException();
stream.Seek(8, SeekOrigin.Begin);
}
else
{
throw new ConnectionException();
}
var bufferStream = new BufferStream(_bufferManager);
if (_informationVersion3.CryptoAlgorithm.HasFlag(SecureVersion3.CryptoAlgorithm.Aes256))
{
byte[] iv = new byte[16];
stream.Read(iv, 0, iv.Length);
using (var aes = Aes.Create())
{
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
using (CryptoStream cs = new CryptoStream(new WrapperStream(bufferStream, true), aes.CreateDecryptor(_informationVersion3.OtherCryptoKey, iv), CryptoStreamMode.Write))
using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
{
int length;
while ((length = stream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
{
cs.Write(safeBuffer.Value, 0, length);
}
}
}
}
else
{
throw new ConnectionException();
}
bufferStream.Seek(0, SeekOrigin.Begin);
return bufferStream;
}
}
else
{
throw new ConnectionException();
}
}
catch (ConnectionException e)
{
throw e;
}
catch (Exception e)
{
throw new ConnectionException(e.Message, e);
}
}
}