예제 #1
0
        public void Test_CacheStream()
        {
            //for (int i = 0; i < 10; i++)
            Parallel.For(0, 32, new ParallelOptions() { MaxDegreeOfParallelism = 64 }, i =>
            {
                //using (MemoryStream stream = new MemoryStream())
                using (BufferStream bufferStream = new BufferStream(_bufferManager))
                using (CacheStream stream = new CacheStream(bufferStream, 1024, _bufferManager))
                {
                    byte[] buffer = _bufferManager.TakeBuffer(1024 * 1024); //new byte[_random.Next(128, 1024 * 1024 * 10)];
                    long seek = _random.Next(64, buffer.Length);
                    //long seek = 0;

                    _random.NextBytes(buffer);

                    stream.Write(buffer, 0, buffer.Length);
                    stream.Position = seek;

                    byte[] buff2 = _bufferManager.TakeBuffer(buffer.Length); //new byte[buffer.Length];
                    stream.Read(buff2, (int)seek, buff2.Length - (int)seek);

                    if (!CollectionUtilities.Equals(buffer, (int)seek, buff2, (int)seek, buffer.Length - (int)seek))
                    {
                        Assert.IsTrue(CollectionUtilities.Equals(buffer, (int)seek, buff2, (int)seek, buffer.Length - (int)seek));
                    }

                    _bufferManager.ReturnBuffer(buffer);
                    _bufferManager.ReturnBuffer(buff2);
                }
            });

            using (MemoryStream mstream = new MemoryStream())
            using (BufferStream bufferStream = new BufferStream(_bufferManager))
            using (CacheStream stream = new CacheStream(bufferStream, 1024, _bufferManager))
            {
                for (int i = 0; i < 1024 * 1024; i++)
                {
                    var v = (byte)_random.Next(0, 255);
                    mstream.WriteByte(v);
                    stream.WriteByte(v);
                }

                mstream.Seek(0, SeekOrigin.Begin);
                stream.Seek(0, SeekOrigin.Begin);

                Assert.IsTrue(mstream.Length == stream.Length);

                for (int i = 0; i < 1024 * 1024; i++)
                {
                    Assert.IsTrue(mstream.ReadByte() == stream.ReadByte());
                }
            }
        }
예제 #2
0
        public static string GetSignature(Certificate certificate)
        {
            if (certificate == null || certificate.Nickname == null || certificate.PublicKey == null) return null;

            try
            {
                if (certificate.DigitalSignatureAlgorithm == DigitalSignatureAlgorithm.EcDsaP521_Sha256
                    || certificate.DigitalSignatureAlgorithm == DigitalSignatureAlgorithm.Rsa2048_Sha256)
                {
                    using (BufferStream bufferStream = new BufferStream(_bufferManager))
                    {
                        Signature.WriteString(bufferStream, certificate.Nickname);
                        bufferStream.Write(certificate.PublicKey, 0, certificate.PublicKey.Length);
                        bufferStream.Seek(0, SeekOrigin.Begin);

                        var signature = certificate.Nickname + "@" + NetworkConverter.ToBase64UrlString(Sha256.ComputeHash(bufferStream));
                        return _signatureCache.GetValue(signature, certificate);
                    }
                }

                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }
예제 #3
0
        public override void Send(Stream stream, TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
            if (!_connect) throw new ConnectionException();
            if (stream == null) throw new ArgumentNullException(nameof(stream));
            if (stream.Length == 0) throw new ArgumentOutOfRangeException(nameof(stream));

            lock (_sendLock)
            {
                using (RangeStream targetStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position, true))
                {
                    try
                    {
                        _sendStopwatch.Restart();

                        Stream headerStream = new BufferStream(_bufferManager);
                        headerStream.Write(NetworkConverter.GetBytes((int)targetStream.Length), 0, 4);

                        using (Stream dataStream = new UniteStream(headerStream, new WrapperStream(targetStream, true)))
                        using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 32))
                        {
                            for (;;)
                            {
                                var sendLength = (int)Math.Min(dataStream.Length - dataStream.Position, safeBuffer.Value.Length);
                                if (sendLength == 0) break;

                                if (_bandwidthLimit != null && _bandwidthLimit.Out != 0)
                                {
                                    sendLength = _bandwidthLimit.GetOutBandwidth(this, sendLength);
                                    if (sendLength < 0) throw new ConnectionException();
                                }

                                dataStream.Read(safeBuffer.Value, 0, sendLength);

                                var time = Connection.CheckTimeout(_sendStopwatch.Elapsed, timeout);
                                time = (time < _sendTimeSpan) ? time : _sendTimeSpan;

                                _cap.Send(safeBuffer.Value, 0, sendLength, time);

                                _aliveStopwatch.Restart();
                                _sentByteCount.Add(sendLength);
                            }
                        }

                        _aliveTimer.Change(1000 * 30);
                    }
                    catch (ConnectionException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new ConnectionException(e.Message, e);
                    }
                }
            }
        }
예제 #4
0
        public override Stream Receive(TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
            if (!_connect) throw new ConnectionException();

            lock (_receiveLock)
            {
                try
                {
                    _receiveStopwatch.Restart();

                    Restart:;

                    int length = 0;

                    {
                        byte[] lengthBuffer = new byte[4];

                        var time = Connection.CheckTimeout(_receiveStopwatch.Elapsed, timeout);
                        time = (time < _receiveTimeSpan) ? time : _receiveTimeSpan;

                        _cap.Receive(lengthBuffer, time);

                        _receivedByteCount.Add(4);

                        length = NetworkConverter.ToInt32(lengthBuffer);
                    }

                    if (length == 0)
                    {
                        Thread.Sleep(300);
                        goto Restart;
                    }
                    else if (length > _maxReceiveCount)
                    {
                        throw new ConnectionException();
                    }

                    BufferStream bufferStream = null;

                    try
                    {
                        bufferStream = new BufferStream(_bufferManager);

                        using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 32))
                        {
                            do
                            {
                                int receiveLength = Math.Min(safeBuffer.Value.Length, length);

                                var time = Connection.CheckTimeout(_receiveStopwatch.Elapsed, timeout);
                                time = (time < _receiveTimeSpan) ? time : _receiveTimeSpan;

                                if (_bandwidthLimit != null && _bandwidthLimit.In != 0)
                                {
                                    if (_cap.Available == 0)
                                    {
                                        Thread.Sleep(300);
                                        continue;
                                    }

                                    receiveLength = _bandwidthLimit.GetInBandwidth(this, Math.Min(_cap.Available, receiveLength));
                                    if (receiveLength < 0) throw new ConnectionException();
                                }

                                _cap.Receive(safeBuffer.Value, 0, receiveLength, time);

                                _receivedByteCount.Add(receiveLength);
                                bufferStream.Write(safeBuffer.Value, 0, receiveLength);

                                length -= receiveLength;
                            } while (length > 0);
                        }
                    }
                    catch (Exception e)
                    {
                        if (bufferStream != null)
                        {
                            bufferStream.Dispose();
                        }

                        throw e;
                    }

                    bufferStream.Seek(0, SeekOrigin.Begin);
                    return bufferStream;
                }
                catch (ConnectionException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new ConnectionException(e.Message, e);
                }
            }
        }
예제 #5
0
        public override void Send(Stream stream, TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
            if (stream == null) throw new ArgumentNullException("stream");
            if (stream.Length == 0) throw new ArgumentOutOfRangeException("stream");
            if (!_connect) throw new ConnectionException();

            lock (_sendLock)
            {
                try
                {
                    using (RangeStream targetStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position, true))
                    {
                        if (_version.HasFlag(SecureConnectionVersion.Version3))
                        {
                            using (BufferStream bufferStream = new BufferStream(_bufferManager))
                            {
                                bufferStream.SetLength(8);
                                bufferStream.Seek(8, SeekOrigin.Begin);

                                if (_informationVersion3.CryptoAlgorithm.HasFlag(SecureVersion3.CryptoAlgorithm.Aes256))
                                {
                                    byte[] iv = new byte[16];
                                    _random.GetBytes(iv);
                                    bufferStream.Write(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.CreateEncryptor(_informationVersion3.MyCryptoKey, iv), CryptoStreamMode.Write))
                                        {
                                            byte[] sendBuffer = null;

                                            try
                                            {
                                                sendBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                                int i = -1;

                                                while ((i = targetStream.Read(sendBuffer, 0, sendBuffer.Length)) > 0)
                                                {
                                                    cs.Write(sendBuffer, 0, i);
                                                }
                                            }
                                            finally
                                            {
                                                if (sendBuffer != null)
                                                {
                                                    _bufferManager.ReturnBuffer(sendBuffer);
                                                }
                                            }
                                        }
                                    }
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }

                                _totalSendSize += (bufferStream.Length - 8);

                                bufferStream.Seek(0, SeekOrigin.Begin);

                                byte[] totalSendSizeBuff = NetworkConverter.GetBytes(_totalSendSize);
                                bufferStream.Write(totalSendSizeBuff, 0, totalSendSizeBuff.Length);

                                if (_informationVersion3.HashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                                {
                                    bufferStream.Seek(0, SeekOrigin.Begin);
                                    byte[] hmacBuff = HmacSha256.ComputeHash(bufferStream, _informationVersion3.MyHmacKey);

                                    bufferStream.Seek(0, SeekOrigin.End);
                                    bufferStream.Write(hmacBuff, 0, hmacBuff.Length);
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }

                                bufferStream.Seek(0, SeekOrigin.Begin);

                                _connection.Send(bufferStream, timeout, options);
                            }
                        }
                        else
                        {
                            throw new ConnectionException();
                        }
                    }
                }
                catch (ConnectionException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new ConnectionException(e.Message, e);
                }
            }
        }
예제 #6
0
        private static Stream AddPadding(Stream stream, int size)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            try
            {
                byte[] seedBuffer = new byte[4];
                _random.GetBytes(seedBuffer);
                Random random = new Random(NetworkConverter.ToInt32(seedBuffer));

                BufferStream metadataStream = new BufferStream(_bufferManager);
                byte[] lengthBuffer = NetworkConverter.GetBytes((int)stream.Length);
                metadataStream.Write(lengthBuffer, 0, lengthBuffer.Length);

                int paddingLength = size - ((int)stream.Length + 4);

                BufferStream paddingStream = new BufferStream(_bufferManager);

                {
                    byte[] buffer = null;

                    try
                    {
                        buffer = _bufferManager.TakeBuffer(1024);

                        while (paddingLength > 0)
                        {
                            int writeSize = Math.Min(paddingLength, buffer.Length);

                            random.NextBytes(buffer);
                            paddingStream.Write(buffer, 0, writeSize);

                            paddingLength -= writeSize;
                        }
                    }
                    finally
                    {
                        _bufferManager.ReturnBuffer(buffer);
                    }
                }

                return new UniteStream(metadataStream, new WrapperStream(stream, true), paddingStream);
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
        public override System.IO.Stream Receive(TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
            if (!_connect) throw new ConnectionException();

            lock (_receiveLock)
            {
                Stream stream = null;

                try
                {
                    stream = _connection.Receive(timeout, options);

                    var version = (byte)stream.ReadByte();

                    Stream dataStream = null;

                    try
                    {
                        dataStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position);

                        if (version == (byte)0)
                        {
                            return dataStream;
                        }
                        else if (version == (byte)1)
                        {
                            BufferStream deflateBufferStream = null;

                            try
                            {
                                deflateBufferStream = new BufferStream(_bufferManager);

                                using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                                using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                                {
                                    int length;

                                    while ((length = deflateStream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                    {
                                        deflateBufferStream.Write(safeBuffer.Value, 0, length);

                                        if (deflateBufferStream.Length > _maxReceiveCount) throw new ConnectionException();
                                    }
                                }
                            }
                            catch (Exception e)
                            {
                                if (deflateBufferStream != null)
                                {
                                    deflateBufferStream.Dispose();
                                }

                                throw e;
                            }

            #if DEBUG
                            Debug.WriteLine("Receive : {0}→{1} {2}",
                                NetworkConverter.ToSizeString(stream.Length),
                                NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                NetworkConverter.ToSizeString(stream.Length - deflateBufferStream.Length));
            #endif

                            deflateBufferStream.Seek(0, SeekOrigin.Begin);
                            dataStream.Dispose();

                            return deflateBufferStream;
                        }
                        else
                        {
                            throw new ArgumentException("ArgumentException");
                        }
                    }
                    catch (ConnectionException e)
                    {
                        if (dataStream != null) dataStream.Dispose();

                        throw e;
                    }
                    catch (Exception e)
                    {
                        if (dataStream != null) dataStream.Dispose();

                        throw new ConnectionException(e.Message, e);
                    }
                }
                catch (ConnectionException e)
                {
                    if (stream != null) stream.Dispose();

                    throw e;
                }
                catch (Exception e)
                {
                    if (stream != null) stream.Dispose();

                    throw new ConnectionException(e.Message, e);
                }
            }
        }
예제 #8
0
        public static string GetSignature(DigitalSignature digitalSignature)
        {
            if (digitalSignature == null || digitalSignature.Nickname == null || digitalSignature.PublicKey == null) return null;

            try
            {
                if (digitalSignature.DigitalSignatureAlgorithm == DigitalSignatureAlgorithm.EcDsaP521_Sha256
                    || digitalSignature.DigitalSignatureAlgorithm == DigitalSignatureAlgorithm.Rsa2048_Sha256)
                {
                    using (BufferStream bufferStream = new BufferStream(_bufferManager))
                    {
                        Signature.WriteString(bufferStream, digitalSignature.Nickname);
                        bufferStream.Write(digitalSignature.PublicKey, 0, digitalSignature.PublicKey.Length);
                        bufferStream.Seek(0, SeekOrigin.Begin);

                        return string.Concat(digitalSignature.Nickname, "@", NetworkConverter.ToBase64UrlString(Sha256.ComputeHash(bufferStream)));
                    }
                }

                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }
예제 #9
0
        private static Stream Decrypt(Stream stream, IExchangeDecrypt privateKey)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (privateKey == null) throw new ArgumentNullException("privateKey");

            try
            {
                byte type = (byte)stream.ReadByte();

                if (type == (byte)ConvertCryptoAlgorithm.Aes256)
                {
                    byte[] cryptoKey;

                    {
                        byte[] lengthBuffer = new byte[4];
                        if (stream.Read(lengthBuffer, 0, lengthBuffer.Length) != lengthBuffer.Length) throw new ArgumentException();
                        int length = NetworkConverter.ToInt32(lengthBuffer);

                        byte[] encryptedBuffer = new byte[length];
                        if (stream.Read(encryptedBuffer, 0, encryptedBuffer.Length) != encryptedBuffer.Length) throw new ArgumentException();

                        cryptoKey = Exchange.Decrypt(privateKey, encryptedBuffer);
                    }

                    BufferStream outStream = null;

                    try
                    {
                        outStream = new BufferStream(_bufferManager);

                        using (Stream dataStream = new WrapperStream(stream, true))
                        {
                            var iv = new byte[32];
                            dataStream.Read(iv, 0, iv.Length);

                            using (var rijndael = new RijndaelManaged() { KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
                            using (var inStream = new RangeStream(dataStream, dataStream.Position, dataStream.Length - dataStream.Position))
                            using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateDecryptor(cryptoKey, iv), CryptoStreamMode.Read))
                            {
                                byte[] buffer = null;

                                try
                                {
                                    buffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                    {
                                        outStream.Write(buffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    _bufferManager.ReturnBuffer(buffer);
                                }
                            }
                        }

                        outStream.Seek(0, SeekOrigin.Begin);
                    }
                    catch (Exception)
                    {
                        if (outStream != null)
                        {
                            outStream.Dispose();
                        }

                        throw;
                    }

                    return outStream;
                }

                throw new NotSupportedException();
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #10
0
        private static Stream Encrypt(Stream stream, IExchangeEncrypt publicKey)
        {
            if (stream == null) throw new ArgumentNullException("stream");
            if (publicKey == null) throw new ArgumentNullException("publicKey");

            try
            {
                BufferStream outStream = null;

                try
                {
                    outStream = new BufferStream(_bufferManager);
                    outStream.WriteByte((byte)ConvertCryptoAlgorithm.Aes256);

                    byte[] cryptoKey = new byte[32];
                    _random.GetBytes(cryptoKey);

                    {
                        var encryptedBuffer = Exchange.Encrypt(publicKey, cryptoKey);
                        outStream.Write(NetworkConverter.GetBytes((int)encryptedBuffer.Length), 0, 4);
                        outStream.Write(encryptedBuffer, 0, encryptedBuffer.Length);
                    }

                    byte[] iv = new byte[32];
                    _random.GetBytes(iv);
                    outStream.Write(iv, 0, iv.Length);

                    using (Stream inStream = new WrapperStream(stream, true))
                    {
                        using (var rijndael = new RijndaelManaged() { KeySize = 256, BlockSize = 256, Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 })
                        using (CryptoStream cs = new CryptoStream(inStream, rijndael.CreateEncryptor(cryptoKey, iv), CryptoStreamMode.Read))
                        {
                            byte[] buffer = null;

                            try
                            {
                                buffer = _bufferManager.TakeBuffer(1024 * 4);

                                int i = -1;

                                while ((i = cs.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    outStream.Write(buffer, 0, i);
                                }
                            }
                            finally
                            {
                                if (buffer != null)
                                {
                                    _bufferManager.ReturnBuffer(buffer);
                                }
                            }
                        }
                    }

                    outStream.Seek(0, SeekOrigin.Begin);
                }
                catch (Exception)
                {
                    if (outStream != null)
                    {
                        outStream.Dispose();
                    }

                    throw;
                }

                return outStream;
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #11
0
        private static Stream Decompress(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            try
            {
                var targetStream = new RangeStream(stream, true);

                byte type = (byte)targetStream.ReadByte();

                if (type == (byte)ConvertCompressionAlgorithm.None)
                {
                    return new RangeStream(targetStream);
                }
                else if (type == (byte)ConvertCompressionAlgorithm.Deflate)
                {
                    using (Stream dataStream = new WrapperStream(targetStream, true))
                    {
                        BufferStream deflateBufferStream = null;

                        try
                        {
                            deflateBufferStream = new BufferStream(_bufferManager);

                            using (DeflateStream deflateStream = new DeflateStream(dataStream, CompressionMode.Decompress, true))
                            {
                                byte[] decompressBuffer = null;

                                try
                                {
                                    decompressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                    int i = -1;

                                    while ((i = deflateStream.Read(decompressBuffer, 0, decompressBuffer.Length)) > 0)
                                    {
                                        deflateBufferStream.Write(decompressBuffer, 0, i);
                                    }
                                }
                                finally
                                {
                                    if (decompressBuffer != null)
                                    {
                                        _bufferManager.ReturnBuffer(decompressBuffer);
                                    }
                                }
                            }

                            deflateBufferStream.Seek(0, SeekOrigin.Begin);

            #if DEBUG
                            Debug.WriteLine("ContentConverter Decompress {3} : {0}→{1} {2}",
                                NetworkConverter.ToSizeString(dataStream.Length),
                                NetworkConverter.ToSizeString(deflateBufferStream.Length),
                                NetworkConverter.ToSizeString(dataStream.Length - deflateBufferStream.Length),
                                ConvertCompressionAlgorithm.Deflate);
            #endif

                            return deflateBufferStream;
                        }
                        catch (Exception)
                        {
                            if (deflateBufferStream != null)
                            {
                                deflateBufferStream.Dispose();
                            }
                        }
                    }
                }

                throw new ArgumentException("ArgumentException");
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }
예제 #12
0
        private static Stream Compress(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            var targetStream = new RangeStream(stream, true);

            List<KeyValuePair<byte, Stream>> list = new List<KeyValuePair<byte, Stream>>();

            try
            {
                targetStream.Seek(0, SeekOrigin.Begin);

                BufferStream deflateBufferStream = null;

                try
                {
                    deflateBufferStream = new BufferStream(_bufferManager);

                    using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                    {
                        byte[] compressBuffer = null;

                        try
                        {
                            compressBuffer = _bufferManager.TakeBuffer(1024 * 4);

                            int i = -1;

                            while ((i = targetStream.Read(compressBuffer, 0, compressBuffer.Length)) > 0)
                            {
                                deflateStream.Write(compressBuffer, 0, i);
                            }
                        }
                        finally
                        {
                            if (compressBuffer != null)
                            {
                                _bufferManager.ReturnBuffer(compressBuffer);
                            }
                        }
                    }

                    deflateBufferStream.Seek(0, SeekOrigin.Begin);

                    list.Add(new KeyValuePair<byte, Stream>((byte)ConvertCompressionAlgorithm.Deflate, deflateBufferStream));
                }
                catch (Exception)
                {
                    if (deflateBufferStream != null)
                    {
                        deflateBufferStream.Dispose();
                    }
                }
            }
            catch (Exception)
            {

            }

            list.Add(new KeyValuePair<byte, Stream>((byte)ConvertCompressionAlgorithm.None, targetStream));

            list.Sort((x, y) =>
            {
                int c = x.Value.Length.CompareTo(y.Value.Length);
                if (c != 0) return c;

                return x.Key.CompareTo(y.Key);
            });

            #if DEBUG
            if (list[0].Value.Length != targetStream.Length)
            {
                Debug.WriteLine("ContentConverter Compress {3} : {0}→{1} {2}",
                    NetworkConverter.ToSizeString(targetStream.Length),
                    NetworkConverter.ToSizeString(list[0].Value.Length),
                    NetworkConverter.ToSizeString(list[0].Value.Length - targetStream.Length),
                    (ConvertCompressionAlgorithm)list[0].Key);
            }
            #endif

            for (int i = 1; i < list.Count; i++)
            {
                list[i].Value.Dispose();
            }

            BufferStream metadataStream = new BufferStream(_bufferManager);
            metadataStream.WriteByte((byte)list[0].Key);

            return new UniteStream(metadataStream, list[0].Value);
        }
예제 #13
0
        private static Stream AddType(Stream stream, string type)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            List<Stream> streams = new List<Stream>();
            Encoding encoding = new UTF8Encoding(false);

            // Type
            if (type != null)
            {
                BufferStream bufferStream = new BufferStream(_bufferManager);
                bufferStream.SetLength(4);
                bufferStream.Seek(4, SeekOrigin.Begin);

                using (WrapperStream wrapperStream = new WrapperStream(bufferStream, true))
                using (StreamWriter writer = new StreamWriter(wrapperStream, encoding))
                {
                    writer.Write(type);
                }

                bufferStream.Seek(0, SeekOrigin.Begin);
                bufferStream.Write(NetworkConverter.GetBytes((int)bufferStream.Length - 4), 0, 4);

                streams.Add(bufferStream);
            }

            streams.Add(new WrapperStream(stream, true));

            return new UniteStream(streams);
        }
        public void Test_Metadata()
        {
            foreach (var a in new DigitalSignatureAlgorithm[] { DigitalSignatureAlgorithm.Rsa2048_Sha256, DigitalSignatureAlgorithm.EcDsaP521_Sha256 })
            {
                var id = new byte[32];
                _random.NextBytes(id);
                var key = new Key(id, HashAlgorithm.Sha256);
                var tag = new Chat("oooo", new byte[32]);
                var miner = new Miner(CashAlgorithm.Version1, -1, TimeSpan.Zero);
                var digitalSignature = new DigitalSignature("123", a);
                var metadata = new ChatMessageMetadata(tag, DateTime.UtcNow, key, miner, digitalSignature);

                ChatMessageMetadata metadata2;
                {
                    var ds = new DataContractSerializer(typeof(ChatMessageMetadata));

                    using (BufferStream stream = new BufferStream(BufferManager.Instance))
                    {
                        using (WrapperStream wrapperStream = new WrapperStream(stream, true))
                        using (XmlDictionaryWriter xmlDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(wrapperStream))
                        {
                            ds.WriteObject(xmlDictionaryWriter, metadata);
                        }

                        stream.Position = 0;

                        using (XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
                        {
                            metadata2 = (ChatMessageMetadata)ds.ReadObject(xmlDictionaryReader);
                        }
                    }
                }

                Assert.AreEqual(metadata, metadata2, "Metadata #1");

                ChatMessageMetadata metadata3;

                using (var metadataStream = metadata.Export(_bufferManager))
                {
                    metadata3 = ChatMessageMetadata.Import(metadataStream, _bufferManager);
                }

                Assert.AreEqual(metadata, metadata3, "Metadata #2");
                Assert.IsTrue(metadata3.VerifyCertificate(), "Metadata #3");
            }
        }
        private void DecodeManagerThread()
        {
            for (; ; )
            {
                Thread.Sleep(1000 * 3);
                if (this.State == ManagerState.Stop) return;

                BackgroundDownloadItem item = null;

                try
                {
                    lock (this.ThisLock)
                    {
                        if (_settings.BackgroundDownloadItems.Count > 0)
                        {
                            item = _settings.BackgroundDownloadItems
                                .Where(n => n.State == BackgroundDownloadState.Decoding)
                                .OrderBy(n => (n.Rank != n.Seed.Rank) ? 0 : 1)
                                .FirstOrDefault();
                        }
                    }
                }
                catch (Exception)
                {
                    return;
                }

                if (item == null) continue;

                try
                {
                    if (item.Rank == 1)
                    {
                        if (!_cacheManager.Contains(item.Seed.Key))
                        {
                            item.State = BackgroundDownloadState.Downloading;
                        }
                        else
                        {
                            item.State = BackgroundDownloadState.Decoding;

                            if (item.Rank < item.Seed.Rank)
                            {
                                string fileName = null;
                                bool largeFlag = false;

                                try
                                {
                                    using (FileStream stream = BackgroundDownloadManager.GetUniqueFileStream(Path.Combine(_workDirectory, "index")))
                                    using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) =>
                                    {
                                        isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item));

                                        if (!isStop && (stream.Length > item.Seed.Length))
                                        {
                                            isStop = true;
                                            largeFlag = true;
                                        }
                                    }, 1024 * 1024, true))
                                    {
                                        fileName = stream.Name;

                                        _cacheManager.Decoding(decodingProgressStream, item.Seed.CompressionAlgorithm, item.Seed.CryptoAlgorithm, item.Seed.CryptoKey,
                                            new KeyCollection() { item.Seed.Key });
                                    }
                                }
                                catch (StopIoException)
                                {
                                    if (File.Exists(fileName))
                                        File.Delete(fileName);

                                    if (largeFlag)
                                    {
                                        throw new Exception();
                                    }

                                    continue;
                                }
                                catch (Exception)
                                {
                                    if (File.Exists(fileName))
                                        File.Delete(fileName);

                                    throw;
                                }

                                Index index;

                                using (FileStream stream = new FileStream(fileName, FileMode.Open))
                                {
                                    index = Index.Import(stream, _bufferManager);
                                }

                                File.Delete(fileName);

                                lock (this.ThisLock)
                                {
                                    this.UncheckState(item.Index);

                                    item.Index = index;

                                    this.CheckState(item.Index);

                                    foreach (var group in item.Index.Groups)
                                    {
                                        foreach (var key in group.Keys)
                                        {
                                            _cacheManager.Lock(key);
                                        }
                                    }

                                    item.Indexes.Add(index);

                                    item.Rank++;

                                    item.State = BackgroundDownloadState.Downloading;
                                }
                            }
                            else
                            {
                                bool largeFlag = false;
                                object value = null;

                                try
                                {
                                    using (Stream stream = new BufferStream(_bufferManager))
                                    using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) =>
                                    {
                                        isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item));

                                        if (!isStop && (stream.Length > item.Seed.Length))
                                        {
                                            isStop = true;
                                            largeFlag = true;
                                        }
                                    }, 1024 * 1024, true))
                                    {
                                        _cacheManager.Decoding(decodingProgressStream, item.Seed.CompressionAlgorithm, item.Seed.CryptoAlgorithm, item.Seed.CryptoKey,
                                            new KeyCollection() { item.Seed.Key });

                                        if (stream.Length != item.Seed.Length) throw new Exception();

                                        stream.Seek(0, SeekOrigin.Begin);

                                        if (item.Type == BackgroundItemType.Link)
                                        {
                                            value = Link.Import(stream, _bufferManager);
                                        }
                                        else if (item.Type == BackgroundItemType.Store)
                                        {
                                            value = Store.Import(stream, _bufferManager);
                                        }
                                    }
                                }
                                catch (StopIoException)
                                {
                                    if (largeFlag)
                                    {
                                        throw new Exception();
                                    }

                                    continue;
                                }
                                catch (Exception)
                                {
                                    throw;
                                }

                                lock (this.ThisLock)
                                {
                                    item.Value = value;

                                    if (item.Seed.Key != null)
                                    {
                                        _cacheManager.Unlock(item.Seed.Key);
                                    }

                                    foreach (var index in item.Indexes)
                                    {
                                        foreach (var group in index.Groups)
                                        {
                                            foreach (var key in group.Keys)
                                            {
                                                _cacheManager.Unlock(key);
                                            }
                                        }
                                    }

                                    item.Indexes.Clear();

                                    item.State = BackgroundDownloadState.Completed;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!item.Index.Groups.All(n => _existManager.GetCount(n) >= n.InformationLength))
                        {
                            item.State = BackgroundDownloadState.Downloading;
                        }
                        else
                        {
                            List<Key> keys = new List<Key>();

                            try
                            {
                                foreach (var group in item.Index.Groups.ToArray())
                                {
                                    keys.AddRange(_cacheManager.ParityDecoding(group, (object state2) =>
                                    {
                                        return (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item));
                                    }));
                                }
                            }
                            catch (StopException)
                            {
                                continue;
                            }

                            item.State = BackgroundDownloadState.Decoding;

                            if (item.Rank < item.Seed.Rank)
                            {
                                string fileName = null;
                                bool largeFlag = false;

                                try
                                {
                                    using (FileStream stream = BackgroundDownloadManager.GetUniqueFileStream(Path.Combine(_workDirectory, "index")))
                                    using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) =>
                                    {
                                        isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item));

                                        if (!isStop && (stream.Length > item.Seed.Length))
                                        {
                                            isStop = true;
                                            largeFlag = true;
                                        }
                                    }, 1024 * 1024, true))
                                    {
                                        fileName = stream.Name;

                                        _cacheManager.Decoding(decodingProgressStream, item.Index.CompressionAlgorithm, item.Index.CryptoAlgorithm, item.Index.CryptoKey,
                                            new KeyCollection(keys));
                                    }
                                }
                                catch (StopIoException)
                                {
                                    if (File.Exists(fileName))
                                        File.Delete(fileName);

                                    if (largeFlag)
                                    {
                                        throw new Exception();
                                    }

                                    continue;
                                }
                                catch (Exception)
                                {
                                    if (File.Exists(fileName))
                                        File.Delete(fileName);

                                    throw;
                                }

                                Index index;

                                using (FileStream stream = new FileStream(fileName, FileMode.Open))
                                {
                                    index = Index.Import(stream, _bufferManager);
                                }

                                File.Delete(fileName);

                                lock (this.ThisLock)
                                {
                                    this.UncheckState(item.Index);

                                    item.Index = index;

                                    this.CheckState(item.Index);

                                    foreach (var group in item.Index.Groups)
                                    {
                                        foreach (var key in group.Keys)
                                        {
                                            _cacheManager.Lock(key);
                                        }
                                    }

                                    item.Indexes.Add(index);

                                    item.Rank++;

                                    item.State = BackgroundDownloadState.Downloading;
                                }
                            }
                            else
                            {
                                item.State = BackgroundDownloadState.Decoding;

                                bool largeFlag = false;
                                object value = null;

                                try
                                {
                                    using (Stream stream = new BufferStream(_bufferManager))
                                    using (ProgressStream decodingProgressStream = new ProgressStream(stream, (object sender, long readSize, long writeSize, out bool isStop) =>
                                    {
                                        isStop = (this.State == ManagerState.Stop || !_settings.BackgroundDownloadItems.Contains(item));

                                        if (!isStop && (stream.Length > item.Seed.Length))
                                        {
                                            isStop = true;
                                            largeFlag = true;
                                        }
                                    }, 1024 * 1024, true))
                                    {
                                        _cacheManager.Decoding(decodingProgressStream, item.Index.CompressionAlgorithm, item.Index.CryptoAlgorithm, item.Index.CryptoKey,
                                            new KeyCollection(keys));

                                        if (stream.Length != item.Seed.Length) throw new Exception();

                                        stream.Seek(0, SeekOrigin.Begin);

                                        if (item.Type == BackgroundItemType.Link)
                                        {
                                            value = Link.Import(stream, _bufferManager);
                                        }
                                        else if (item.Type == BackgroundItemType.Store)
                                        {
                                            value = Store.Import(stream, _bufferManager);
                                        }
                                    }
                                }
                                catch (StopIoException)
                                {
                                    if (largeFlag)
                                    {
                                        throw new Exception();
                                    }

                                    continue;
                                }
                                catch (Exception)
                                {
                                    throw;
                                }

                                lock (this.ThisLock)
                                {
                                    item.Value = value;

                                    if (item.Seed.Key != null)
                                    {
                                        _cacheManager.Unlock(item.Seed.Key);
                                    }

                                    foreach (var index in item.Indexes)
                                    {
                                        foreach (var group in index.Groups)
                                        {
                                            foreach (var key in group.Keys)
                                            {
                                                _cacheManager.Unlock(key);
                                            }
                                        }
                                    }

                                    item.Indexes.Clear();

                                    item.State = BackgroundDownloadState.Completed;
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    if (_cacheManager.Contains(item.Seed.Key))
                    {
                        ArraySegment<byte> buffer = new ArraySegment<byte>();

                        try
                        {
                            buffer = _cacheManager[item.Seed.Key];
                        }
                        catch (Exception)
                        {

                        }
                        finally
                        {
                            if (buffer.Array != null)
                            {
                                _bufferManager.ReturnBuffer(buffer.Array);
                            }
                        }
                    }

                    foreach (var index in item.Indexes)
                    {
                        foreach (var group in index.Groups)
                        {
                            foreach (var key in group.Keys)
                            {
                                if (this.State == ManagerState.Stop) return;

                                if (!_cacheManager.Contains(key)) continue;

                                ArraySegment<byte> buffer = new ArraySegment<byte>();

                                try
                                {
                                    buffer = _cacheManager[key];
                                }
                                catch (Exception)
                                {

                                }
                                finally
                                {
                                    if (buffer.Array != null)
                                    {
                                        _bufferManager.ReturnBuffer(buffer.Array);
                                    }
                                }
                            }
                        }
                    }

                    item.State = BackgroundDownloadState.Error;

                    Log.Error(e);
                }
            }
        }
        public void Test_Tag()
        {
            var tag = new Chat("oooo", new byte[32]);

            Chat tag2;
            {
                var ds = new DataContractSerializer(typeof(Chat));

                using (BufferStream stream = new BufferStream(BufferManager.Instance))
                {
                    using (WrapperStream wrapperStream = new WrapperStream(stream, true))
                    using (XmlDictionaryWriter xmlDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(wrapperStream))
                    {
                        ds.WriteObject(xmlDictionaryWriter, tag);
                    }

                    stream.Position = 0;

                    using (XmlDictionaryReader xmlDictionaryReader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
                    {
                        tag2 = (Chat)ds.ReadObject(xmlDictionaryReader);
                    }
                }
            }

            Assert.AreEqual(tag, tag2, "Tag #1");

            Chat tag3;

            using (var tagStream = tag.Export(_bufferManager))
            {
                tag3 = Chat.Import(tagStream, _bufferManager);
            }

            Assert.AreEqual(tag, tag3, "Tag #2");
        }
예제 #17
0
        public override void Connect(TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);

            lock (this.ThisLock)
            {
                try
                {
                    SecureVersion3.ProtocolInformation myProtocol3;
                    SecureVersion3.ProtocolInformation otherProtocol3;

                    {
                        OperatingSystem osInfo = Environment.OSVersion;

                        // Windows Vista�ȏ�B
                        if (osInfo.Platform == PlatformID.Win32NT && osInfo.Version >= new Version(6, 0))
                        {
                            {
                                byte[] sessionId = new byte[32];
                                _random.GetBytes(sessionId);

                                myProtocol3 = new SecureVersion3.ProtocolInformation()
                                {
                                    KeyExchangeAlgorithm = SecureVersion3.KeyExchangeAlgorithm.EcDiffieHellmanP521 | SecureVersion3.KeyExchangeAlgorithm.Rsa2048,
                                    KeyDerivationAlgorithm = SecureVersion3.KeyDerivationAlgorithm.Pbkdf2,
                                    CryptoAlgorithm = SecureVersion3.CryptoAlgorithm.Aes256,
                                    HashAlgorithm = SecureVersion3.HashAlgorithm.Sha256,
                                    SessionId = sessionId,
                                };
                            }
                        }
                        else
                        {
                            {
                                byte[] sessionId = new byte[32];
                                _random.GetBytes(sessionId);

                                myProtocol3 = new SecureVersion3.ProtocolInformation()
                                {
                                    KeyExchangeAlgorithm = SecureVersion3.KeyExchangeAlgorithm.Rsa2048,
                                    KeyDerivationAlgorithm = SecureVersion3.KeyDerivationAlgorithm.Pbkdf2,
                                    CryptoAlgorithm = SecureVersion3.CryptoAlgorithm.Aes256,
                                    HashAlgorithm = SecureVersion3.HashAlgorithm.Sha256,
                                    SessionId = sessionId,
                                };
                            }
                        }
                    }

                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();

                    using (BufferStream stream = new BufferStream(_bufferManager))
                    using (XmlTextWriter xml = new XmlTextWriter(stream, new UTF8Encoding(false)))
                    {
                        xml.WriteStartDocument();

                        xml.WriteStartElement("Protocol");

                        if (_myVersion.HasFlag(SecureConnectionVersion.Version3))
                        {
                            xml.WriteStartElement("SecureConnection");
                            xml.WriteAttributeString("Version", "3");
                            xml.WriteEndElement(); //Protocol
                        }

                        xml.WriteEndElement(); //Configuration

                        xml.WriteEndDocument();
                        xml.Flush();
                        stream.Flush();

                        stream.Seek(0, SeekOrigin.Begin);
                        _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                    }

                    otherProtocol3 = new SecureVersion3.ProtocolInformation();

                    using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                    using (XmlTextReader xml = new XmlTextReader(stream))
                    {
                        while (xml.Read())
                        {
                            if (xml.NodeType == XmlNodeType.Element)
                            {
                                if (xml.LocalName == "SecureConnection")
                                {
                                    if (xml.GetAttribute("Version") == "3")
                                    {
                                        _otherVersion |= SecureConnectionVersion.Version3;
                                    }
                                }
                            }
                        }
                    }

                    _version = _myVersion & _otherVersion;

                    // Version3
                    if (_version.HasFlag(SecureConnectionVersion.Version3))
                    {
                        using (Stream stream = myProtocol3.Export(_bufferManager))
                        {
                            _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                        }

                        using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                        {
                            otherProtocol3 = SecureVersion3.ProtocolInformation.Import(stream, _bufferManager);
                        }

                        var keyExchangeAlgorithm = myProtocol3.KeyExchangeAlgorithm & otherProtocol3.KeyExchangeAlgorithm;
                        var keyDerivationFunctionAlgorithm = myProtocol3.KeyDerivationAlgorithm & otherProtocol3.KeyDerivationAlgorithm;
                        var cryptoAlgorithm = myProtocol3.CryptoAlgorithm & otherProtocol3.CryptoAlgorithm;
                        var hashAlgorithm = myProtocol3.HashAlgorithm & otherProtocol3.HashAlgorithm;

                        byte[] myCryptoKey;
                        byte[] otherCryptoKey;
                        byte[] myHmacKey;
                        byte[] otherHmacKey;

                        byte[] myProtocolHash = null;
                        byte[] otherProtocolHash = null;

                        if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                        {
                            using (var myProtocolHashStream = myProtocol3.Export(_bufferManager))
                            using (var otherProtocolHashStream = otherProtocol3.Export(_bufferManager))
                            {
                                myProtocolHash = Sha256.ComputeHash(myProtocolHashStream);
                                otherProtocolHash = Sha256.ComputeHash(otherProtocolHashStream);
                            }
                        }

                        byte[] seed = null;

                        if (keyExchangeAlgorithm.HasFlag(SecureVersion3.KeyExchangeAlgorithm.EcDiffieHellmanP521))
                        {
                            byte[] publicKey, privateKey;
                            EcDiffieHellmanP521.CreateKeys(out publicKey, out privateKey);

                            {
                                SecureVersion3.ConnectionSignature connectionSignature = new SecureVersion3.ConnectionSignature();
                                connectionSignature.ExchangeKey = publicKey;

                                if (_digitalSignature != null)
                                {
                                    connectionSignature.CreationTime = DateTime.UtcNow;
                                    connectionSignature.ProtocolHash = myProtocolHash;
                                    connectionSignature.CreateCertificate(_digitalSignature);
                                }

                                using (Stream stream = connectionSignature.Export(_bufferManager))
                                {
                                    _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                                }
                            }

                            byte[] otherPublicKey = null;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                SecureVersion3.ConnectionSignature connectionSignature = SecureVersion3.ConnectionSignature.Import(stream, _bufferManager);

                                if (connectionSignature.VerifyCertificate())
                                {
                                    if (connectionSignature.Certificate != null)
                                    {
                                        DateTime now = DateTime.UtcNow;
                                        TimeSpan span = (now > connectionSignature.CreationTime) ? now - connectionSignature.CreationTime : connectionSignature.CreationTime - now;
                                        if (span > new TimeSpan(0, 30, 0)) throw new ConnectionException();

                                        if (!Unsafe.Equals(connectionSignature.ProtocolHash, otherProtocolHash)) throw new ConnectionException();
                                    }

                                    _certificate = connectionSignature.Certificate;
                                    otherPublicKey = connectionSignature.ExchangeKey;
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                seed = EcDiffieHellmanP521.DeriveKeyMaterial(privateKey, otherPublicKey, CngAlgorithm.Sha256);
                            }

                            if (seed == null) throw new ConnectionException();
                        }
                        else if (keyExchangeAlgorithm.HasFlag(SecureVersion3.KeyExchangeAlgorithm.Rsa2048))
                        {
                            byte[] publicKey, privateKey;
                            Rsa2048.CreateKeys(out publicKey, out privateKey);

                            {
                                SecureVersion3.ConnectionSignature connectionSignature = new SecureVersion3.ConnectionSignature();
                                connectionSignature.ExchangeKey = publicKey;

                                if (_digitalSignature != null)
                                {
                                    connectionSignature.CreationTime = DateTime.UtcNow;
                                    connectionSignature.ProtocolHash = myProtocolHash;
                                    connectionSignature.CreateCertificate(_digitalSignature);
                                }

                                using (Stream stream = connectionSignature.Export(_bufferManager))
                                {
                                    _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                                }
                            }

                            byte[] otherPublicKey;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                SecureVersion3.ConnectionSignature connectionSignature = SecureVersion3.ConnectionSignature.Import(stream, _bufferManager);

                                if (connectionSignature.VerifyCertificate())
                                {
                                    if (connectionSignature.Certificate != null)
                                    {
                                        DateTime now = DateTime.UtcNow;
                                        TimeSpan span = (now > connectionSignature.CreationTime) ? now - connectionSignature.CreationTime : connectionSignature.CreationTime - now;
                                        if (span > new TimeSpan(0, 30, 0)) throw new ConnectionException();

                                        if (!Unsafe.Equals(connectionSignature.ProtocolHash, otherProtocolHash)) throw new ConnectionException();
                                    }

                                    _certificate = connectionSignature.Certificate;
                                    otherPublicKey = connectionSignature.ExchangeKey;
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }

                            byte[] mySeed = new byte[128];
                            _random.GetBytes(mySeed);

                            using (MemoryStream stream = new MemoryStream(Rsa2048.Encrypt(otherPublicKey, mySeed)))
                            {
                                _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                            }

                            byte[] otherSeed;

                            using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                            {
                                var buffer = new byte[stream.Length];
                                stream.Read(buffer, 0, buffer.Length);

                                otherSeed = Rsa2048.Decrypt(privateKey, buffer);
                            }

                            if (otherSeed == null) throw new ConnectionException();

                            seed = new byte[Math.Max(mySeed.Length, otherSeed.Length)];
                            Unsafe.Xor(mySeed, otherSeed, seed);
                        }
                        else
                        {
                            throw new ConnectionException();
                        }

                        if (keyDerivationFunctionAlgorithm.HasFlag(SecureVersion3.KeyDerivationAlgorithm.Pbkdf2))
                        {
                            byte[] xorSessionId = new byte[Math.Max(myProtocol3.SessionId.Length, otherProtocol3.SessionId.Length)];
                            Unsafe.Xor(myProtocol3.SessionId, otherProtocol3.SessionId, xorSessionId);

                            HMAC hmac = null;

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                hmac = new HMACSHA256();
                                hmac.HashName = "SHA256";
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            Pbkdf2 pbkdf2 = new Pbkdf2(hmac, seed, xorSessionId, 1024);

                            int cryptoKeyLength;
                            int hmacKeyLength;

                            if (cryptoAlgorithm.HasFlag(SecureVersion3.CryptoAlgorithm.Aes256))
                            {
                                cryptoKeyLength = 32;
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            if (hashAlgorithm.HasFlag(SecureVersion3.HashAlgorithm.Sha256))
                            {
                                hmacKeyLength = 32;
                            }
                            else
                            {
                                throw new ConnectionException();
                            }

                            myCryptoKey = new byte[cryptoKeyLength];
                            otherCryptoKey = new byte[cryptoKeyLength];
                            myHmacKey = new byte[hmacKeyLength];
                            otherHmacKey = new byte[hmacKeyLength];

                            using (MemoryStream stream = new MemoryStream(pbkdf2.GetBytes((cryptoKeyLength + hmacKeyLength) * 2)))
                            {
                                if (_type == SecureConnectionType.Connect)
                                {
                                    stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                                    stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                                    stream.Read(myHmacKey, 0, myHmacKey.Length);
                                    stream.Read(otherHmacKey, 0, otherHmacKey.Length);
                                }
                                else if (_type == SecureConnectionType.Accept)
                                {
                                    stream.Read(otherCryptoKey, 0, otherCryptoKey.Length);
                                    stream.Read(myCryptoKey, 0, myCryptoKey.Length);
                                    stream.Read(otherHmacKey, 0, otherHmacKey.Length);
                                    stream.Read(myHmacKey, 0, myHmacKey.Length);
                                }
                                else
                                {
                                    throw new ConnectionException();
                                }
                            }
                        }
                        else
                        {
                            throw new ConnectionException();
                        }

                        _informationVersion3 = new InformationVersion3();
                        _informationVersion3.CryptoAlgorithm = cryptoAlgorithm;
                        _informationVersion3.HashAlgorithm = hashAlgorithm;
                        _informationVersion3.MyCryptoKey = myCryptoKey;
                        _informationVersion3.OtherCryptoKey = otherCryptoKey;
                        _informationVersion3.MyHmacKey = myHmacKey;
                        _informationVersion3.OtherHmacKey = otherHmacKey;
                    }
                    else
                    {
                        throw new ConnectionException();
                    }
                }
                catch (ConnectionException e)
                {
                    throw e;
                }
                catch (Exception e)
                {
                    throw new ConnectionException(e.Message, e);
                }

                _connect = true;
            }
        }
예제 #18
0
        public override void Connect(TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);

            lock (this.ThisLock)
            {
                try
                {
                    var stopwatch = new Stopwatch();
                    stopwatch.Start();

                    using (BufferStream stream = new BufferStream(_bufferManager))
                    {
                        byte[] buffer = NetworkConverter.GetBytes((uint)_myCompressAlgorithm);
                        stream.Write(buffer, 0, buffer.Length);
                        stream.Flush();
                        stream.Seek(0, SeekOrigin.Begin);

                        _connection.Send(stream, CheckTimeout(stopwatch.Elapsed, timeout));
                    }

                    using (Stream stream = _connection.Receive(CheckTimeout(stopwatch.Elapsed, timeout)))
                    {
                        byte[] buffer = new byte[4];
                        stream.Read(buffer, 0, buffer.Length);

                        _otherCompressAlgorithm = (CompressAlgorithm)NetworkConverter.ToUInt32(buffer);
                    }
                }
                catch (ConnectionException ex)
                {
                    throw ex;
                }
                catch (Exception ex)
                {
                    throw new ConnectionException(ex.Message, ex);
                }

                _connect = true;
            }
        }
예제 #19
0
        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();
                            }

                            BufferStream 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))
                                    {
                                        byte[] receiveBuffer = null;

                                        try
                                        {
                                            receiveBuffer = _bufferManager.TakeBuffer(1024 * 4);

                                            int i = -1;

                                            while ((i = stream.Read(receiveBuffer, 0, receiveBuffer.Length)) > 0)
                                            {
                                                cs.Write(receiveBuffer, 0, i);
                                            }
                                        }
                                        finally
                                        {
                                            if (receiveBuffer != null)
                                            {
                                                _bufferManager.ReturnBuffer(receiveBuffer);
                                            }
                                        }
                                    }
                                }
                            }
                            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);
                }
            }
        }
예제 #20
0
        public override void Send(System.IO.Stream stream, TimeSpan timeout, Information options)
        {
            if (_disposed) throw new ObjectDisposedException(this.GetType().FullName);
            if (!_connect) throw new ConnectionException();
            if (stream == null) throw new ArgumentNullException(nameof(stream));
            if (stream.Length == 0) throw new ArgumentOutOfRangeException(nameof(stream));

            bool isCompress = true;

            if (options != null)
            {
                if (options.Contains("IsCompress")) isCompress = (bool)options["IsCompress"];
            }

            lock (_sendLock)
            {
                using (RangeStream targetStream = new RangeStream(stream, stream.Position, stream.Length - stream.Position, true))
                {
                    try
                    {
                        var list = new List<KeyValuePair<byte, Stream>>();

                        if (isCompress)
                        {
                            if (_otherCompressAlgorithm.HasFlag(CompressAlgorithm.Deflate))
                            {
                                BufferStream deflateBufferStream = null;

                                try
                                {
                                    deflateBufferStream = new BufferStream(_bufferManager);

                                    using (DeflateStream deflateStream = new DeflateStream(deflateBufferStream, CompressionMode.Compress, true))
                                    using (var safeBuffer = _bufferManager.CreateSafeBuffer(1024 * 4))
                                    {
                                        int length;

                                        while ((length = targetStream.Read(safeBuffer.Value, 0, safeBuffer.Value.Length)) > 0)
                                        {
                                            deflateStream.Write(safeBuffer.Value, 0, length);
                                        }
                                    }

                                    deflateBufferStream.Seek(0, SeekOrigin.Begin);

                                    list.Add(new KeyValuePair<byte, Stream>((byte)1, deflateBufferStream));
                                }
                                catch (Exception e)
                                {
                                    if (deflateBufferStream != null)
                                    {
                                        deflateBufferStream.Dispose();
                                    }

                                    throw e;
                                }
                            }
                        }

                        list.Add(new KeyValuePair<byte, Stream>((byte)0, new WrapperStream(targetStream, true)));

                        list.Sort((x, y) =>
                        {
                            int c = x.Value.Length.CompareTo(y.Value.Length);
                            if (c != 0) return c;

                            return x.Key.CompareTo(y.Key);
                        });

            #if DEBUG
                        if (list[0].Value.Length != targetStream.Length)
                        {
                            Debug.WriteLine("Send : {0}→{1} {2}",
                                NetworkConverter.ToSizeString(targetStream.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length),
                                NetworkConverter.ToSizeString(list[0].Value.Length - targetStream.Length));
                        }
            #endif

                        for (int i = 1; i < list.Count; i++)
                        {
                            list[i].Value.Dispose();
                        }

                        var headerStream = new BufferStream(_bufferManager);
                        headerStream.WriteByte((byte)list[0].Key);

                        using (var dataStream = new UniteStream(headerStream, list[0].Value))
                        {
                            _connection.Send(dataStream, timeout, options);
                        }
                    }
                    catch (ConnectionException e)
                    {
                        throw e;
                    }
                    catch (Exception e)
                    {
                        throw new ConnectionException(e.Message, e);
                    }
                }
            }
        }
예제 #21
0
        private static Stream AddHash(Stream stream)
        {
            if (stream == null) throw new ArgumentNullException("stream");

            try
            {
                var targetStream = new RangeStream(stream, true);

                BufferStream metadataStream = new BufferStream(_bufferManager);
                metadataStream.WriteByte((byte)ConvertHashAlgorithm.Sha256);

                targetStream.Seek(0, SeekOrigin.Begin);
                var hash = Sha256.ComputeHash(targetStream);

                BufferStream hashStream = new BufferStream(_bufferManager);
                hashStream.Write(hash, 0, hash.Length);

                return new UniteStream(metadataStream, targetStream, hashStream);
            }
            catch (Exception e)
            {
                throw new ArgumentException(e.Message, e);
            }
        }