public EncryptedSocket(EncryptionTypes allowedEncryption)
        {
#if NETSTANDARD1_5
            random = RandomNumberGenerator.Create();
            hasher = SHA1.Create();
#else
            random = RNGCryptoServiceProvider.Create();
            hasher = HashAlgoFactory.Create <SHA1>();
#endif

            GenerateX();
            GenerateY();

            InitialPayload       = BufferManager.EmptyBuffer;
            RemoteInitialPayload = BufferManager.EmptyBuffer;

            doneSendCallback             = doneSend;
            doneReceiveCallback          = doneReceive;
            doneReceiveYCallback         = delegate { doneReceiveY(); };
            doneSynchronizeCallback      = delegate { doneSynchronize(); };
            fillSynchronizeBytesCallback = fillSynchronizeBytes;

            bytesReceived = 0;

            SetMinCryptoAllowed(allowedEncryption);
        }
        private void EndCheckEncryption(IAsyncResult result)
        {
            PeerId id = (PeerId)result.AsyncState;

            byte[] initialData;
            try
            {
                EncryptorFactory.EndCheckEncryption(result, out initialData);
                if (initialData != null && initialData.Length > 0)
                {
                    throw new EncryptionException("unhandled initial data");
                }

                EncryptionTypes e = engine.Settings.AllowedEncryption;
                if (id.Encryptor is RC4 && !Toolbox.HasEncryption(e, EncryptionTypes.RC4Full) ||
                    id.Encryptor is RC4Header && !Toolbox.HasEncryption(e, EncryptionTypes.RC4Header) ||
                    id.Encryptor is PlainTextEncryption && !Toolbox.HasEncryption(e, EncryptionTypes.PlainText))
                {
                    CleanupSocket(id, id.Encryptor.GetType().Name + " encryption is not enabled");
                }
                else
                {
                    // Create a handshake message to send to the peer
                    HandshakeMessage handshake = new HandshakeMessage(id.TorrentManager.InfoHash, engine.PeerId, VersionInfo.ProtocolStringV100);
                    SendMessage(id, handshake, this.handshakeSentCallback);
                }
            }
            catch
            {
                id.Peer.Encryption &= ~EncryptionTypes.RC4Full;
                id.Peer.Encryption &= ~EncryptionTypes.RC4Header;
                CleanupSocket(id, "Failed encryptor check");
            }
        }
Beispiel #3
0
        /// <summary>
        /// The method for encrypt or dncrypt the specified data.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="source">The source data for <paramref name="type"/>.</param>
        /// <param name="key">Gets or sets the secret key for the symmetric algorithm.</param>
        /// <param name="iv">The initialization vector (IV) to use to derive the key.</param>
        /// <param name="keySize">Size of the key.</param>
        /// <param name="mode">The mode.</param>
        /// <param name="padding">The padding.</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException">source</exception>
        internal static byte[] EncryptOrDecrypt(EncryptionTypes type, byte[] source, byte[] key, byte[] iv, int keySize = 128, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {
            ArgumentValidator.Validate(source, key);

            byte[] output = null;

            using (TSymmetricAlgorithm provider = new TSymmetricAlgorithm()
            {
                KeySize = keySize, Mode = mode, Padding = padding, Key = key
            })
            {
                if (iv != null)
                {
                    provider.IV = iv;
                }
                using (ICryptoTransform encryptor = type == EncryptionTypes.Encrypt ? provider.CreateEncryptor() : provider.CreateDecryptor())
                {
                    output = encryptor.TransformFinalBlock(source, 0, source.Length);
                }

                provider.Clear();
            }

            return(output);
        }
        public PeerBEncryption(InfoHash[] possibleSkeYs, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            _possibleSkeYs = possibleSkeYs;

            _gotVerificationCallback = GotVerification;
            _gotPadCCallback = GotPadC;
        }
Beispiel #5
0
 public BroadcastMessageCommand(Guid[] clientList, string response, ResponseTypes responseType, MessageHeader header)
 {
     _clientList      = clientList;
     _response        = response;
     _responseType    = responseType;
     _compressionType = header.CompressionType;
     _encryptionType  = header.EncryptionHeader.EncryptionType;
 }
Beispiel #6
0
        public PeerAEncryption(InfoHash infoHash, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            _gotVerificationCallback = GotVerification;
            _gotPadDCallback         = GotPadD;

            SKEY = infoHash;
        }
Beispiel #7
0
        public PeerAEncryption(InfoHash InfoHash, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            gotVerificationCallback = new AsyncCallback(gotVerification);
            gotPadDCallback = new AsyncCallback(gotPadD);

            SKEY = InfoHash;
        }
Beispiel #8
0
        public PeerBEncryption(InfoHash[] possibleSKEYs, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            _possibleSKEYs = possibleSKEYs;

            _gotVerificationCallback = GotVerification;
            _gotPadCCallback         = gotPadC;
        }
        public PeerAEncryption(InfoHash infoHash, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            _gotVerificationCallback = GotVerification;
            _gotPadDCallback = GotPadD;

            Skey = infoHash;
        }
Beispiel #10
0
        public PeerAEncryption(InfoHash InfoHash, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            gotVerificationCallback = new AsyncCallback(gotVerification);
            gotPadDCallback         = new AsyncCallback(gotPadD);

            SKEY = InfoHash;
        }
 public SendServerResponseCommand(Guid clientId, string response, ResponseTypes responseType, MessageHeader header)
 {
     _clientId = clientId;
     _response = response;
     _responseType = responseType;
     _compressionType = header.CompressionType;
     _encryptionType = header.EncryptionHeader.EncryptionType;
 }
 public BroadcastMessageCommand(Guid[] clientList, string response, ResponseTypes responseType, MessageHeader header)
 {
     _clientList = clientList;
     _response = response;
     _responseType = responseType;
     _compressionType = header.CompressionType;
     _encryptionType = header.EncryptionHeader.EncryptionType;
 }
Beispiel #13
0
        public PeerBEncryption(InfoHash[] possibleSKEYs, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            this.possibleSKEYs = possibleSKEYs;

            gotVerificationCallback = new AsyncCallback(gotVerification);
            gotPadCCallback         = new AsyncCallback(gotPadC);
        }
 public SendServerResponseCommand(Guid clientId, string response, ResponseTypes responseType, MessageHeader header)
 {
     _clientId        = clientId;
     _response        = response;
     _responseType    = responseType;
     _compressionType = header.CompressionType;
     _encryptionType  = header.EncryptionHeader.EncryptionType;
 }
        public PeerAEncryption(InfoHash InfoHash, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            gotVerificationCallback = gotVerification;
            gotPadDCallback = gotPadD;

            SKEY = InfoHash;
        }
Beispiel #16
0
        public PeerBEncryption(InfoHash[] possibleSKEYs, EncryptionTypes allowedEncryption)
            : base(allowedEncryption)
        {
            this.possibleSKEYs = possibleSKEYs;

            gotVerificationCallback = new AsyncCallback(gotVerification);
            gotPadCCallback = new AsyncCallback(gotPadC);
        }
Beispiel #17
0
        public static Encryption Generate(EncryptionTypes encryptionType, ArraySegment <byte> data, byte[] password)
        {
            if (encryptionType == EncryptionTypes.Aes256)
            {
                return(new Aes256Encryption(data, password));
            }

            throw new ArgumentException(string.Format("Encryption type not implemented {0}", encryptionType));
        }
Beispiel #18
0
        async Task Handshake(EncryptionTypes outgoingEncryption, EncryptionTypes incomingEncryption, bool appendInitialPayload)
        {
            var handshakeIn  = new HandshakeMessage(InfoHash, IncomingId, VersionInfo.ProtocolStringV100);
            var handshakeOut = new HandshakeMessage(InfoHash, OutgoingId, VersionInfo.ProtocolStringV100);

            var incomingTask = EncryptorFactory.CheckIncomingConnectionAsync(Incoming, incomingEncryption, new EngineSettings(), SKeys);
            var outgoingTask = EncryptorFactory.CheckOutgoingConnectionAsync(Outgoing, outgoingEncryption, new EngineSettings(), InfoHash, appendInitialPayload ? handshakeOut : null);

            // If the handshake was not part of the initial payload, send it now.
            var outgoingCrypto = await outgoingTask;

            if (!appendInitialPayload)
            {
                await PeerIO.SendMessageAsync(Outgoing, outgoingCrypto.Encryptor, handshakeOut, null, null, null);
            }

            // Receive the handshake and make sure it decrypted correctly.
            var incomingCrypto = await incomingTask;

            Assert.AreEqual(OutgoingId, incomingCrypto.Handshake.PeerId, "#1a");

            // Send the other handshake.
            await PeerIO.SendMessageAsync(Incoming, incomingCrypto.Encryptor, handshakeIn, null, null, null);

            // Receive the other handshake and make sure it decrypted ok on the other side.
            handshakeIn = await PeerIO.ReceiveHandshakeAsync(Outgoing, outgoingCrypto.Decryptor);

            Assert.AreEqual(IncomingId, handshakeIn.PeerId, "#1b");

            // Make sure we got the crypto we asked for.
            if (incomingEncryption == EncryptionTypes.PlainText)
            {
                Assert.IsInstanceOf <PlainTextEncryption> (incomingCrypto.Decryptor, "#2");
            }
            else if (incomingEncryption == EncryptionTypes.RC4Full)
            {
                Assert.IsInstanceOf <RC4> (incomingCrypto.Decryptor, "#3");
            }
            else if (incomingEncryption == EncryptionTypes.RC4Header)
            {
                Assert.IsInstanceOf <RC4Header> (incomingCrypto.Decryptor, "#4");
            }

            if (outgoingEncryption == EncryptionTypes.PlainText)
            {
                Assert.IsInstanceOf <PlainTextEncryption> (outgoingCrypto.Decryptor, "#5");
            }
            else if (outgoingEncryption == EncryptionTypes.RC4Full)
            {
                Assert.IsInstanceOf <RC4> (outgoingCrypto.Decryptor, "#6");
            }
            else if (outgoingEncryption == EncryptionTypes.RC4Header)
            {
                Assert.IsInstanceOf <RC4Header> (outgoingCrypto.Decryptor, "#7");
            }
        }
Beispiel #19
0
        public static bool CheckEncryptionType(EncryptionTypes encryptionType, bool throwException)
        {
            var valid = Enum.IsDefined(typeof(EncryptionTypes), encryptionType);

            if (!valid && throwException)
            {
                throw new ArgumentException(string.Format("Invalid encryption type {0}", encryptionType));
            }
            return(valid);
        }
Beispiel #20
0
 public EngineSettings(string defaultSavePath, int listenPort, int globalMaxConnections, int globalHalfOpenConnections, int globalMaxDownloadSpeed, int globalMaxUploadSpeed, EncryptionTypes allowedEncryption)
 {
     this.globalMaxConnections         = globalMaxConnections;
     this.globalMaxDownloadSpeed       = globalMaxDownloadSpeed;
     this.globalMaxUploadSpeed         = globalMaxUploadSpeed;
     this.globalMaxHalfOpenConnections = globalHalfOpenConnections;
     this.listenPort        = listenPort;
     this.allowedEncryption = allowedEncryption;
     this.savePath          = defaultSavePath;
 }
Beispiel #21
0
        private void Handshake(EncryptionTypes encryptionA, EncryptionTypes encryptionB, bool addInitial)
        {
            HandshakeMessage m = new HandshakeMessage(rig.Torrent.InfoHash, "12345123451234512345", VersionInfo.ProtocolStringV100);

            byte[] handshake = m.Encode();

            PeerAEncryption a = new PeerAEncryption(rig.Torrent.InfoHash, encryptionA);

            if (addInitial)
            {
                a.AddPayload(handshake);
            }

            PeerBEncryption b = new PeerBEncryption(new InfoHash[] { rig.Torrent.InfoHash }, encryptionB);

            var resultA = a.HandshakeAsync(conn.Outgoing);
            var resultB = b.HandshakeAsync(conn.Incoming);

            if (!Task.WhenAll(resultA, resultB).Wait(5000))
            {
                Assert.Fail("Could not handshake");
            }


            HandshakeMessage d = new HandshakeMessage();

            if (!addInitial)
            {
                a.Encrypt(handshake, 0, handshake.Length);
                b.Decrypt(handshake, 0, handshake.Length);
                d.Decode(handshake, 0, handshake.Length);
            }
            else
            {
                d.Decode(b.InitialData, 0, b.InitialData.Length);
            }
            Assert.AreEqual(m, d);


            if (encryptionA == EncryptionTypes.RC4Full || encryptionB == EncryptionTypes.RC4Full)
            {
                Assert.IsTrue(a.Encryptor is RC4);
                Assert.IsTrue(b.Encryptor is RC4);
            }
            else if (encryptionA == EncryptionTypes.RC4Header || encryptionB == EncryptionTypes.RC4Header)
            {
                Assert.IsTrue(a.Encryptor is RC4Header);
                Assert.IsTrue(b.Encryptor is RC4Header);
            }
            else if (encryptionA == EncryptionTypes.PlainText || encryptionB == EncryptionTypes.PlainText)
            {
                Assert.IsTrue(a.Encryptor is PlainTextEncryption);
                Assert.IsTrue(b.Encryptor is PlainTextEncryption);
            }
        }
Beispiel #22
0
        public Peer(string peerId, Uri connectionUri, EncryptionTypes encryption)
        {
            if (peerId == null)
                throw new ArgumentNullException("peerId");
            if (connectionUri == null)
                throw new ArgumentNullException("connectionUri");

            this.connectionUri = connectionUri;
            this.encryption = encryption;
            this.peerId = peerId;
        }
Beispiel #23
0
        protected EncryptedSocket(EncryptionTypes allowedEncryption)
        {
            random = RandomNumberGenerator.Create();
            hasher = HashAlgoFactory.Create <SHA1> ();

            X = new byte[20];
            random.GetBytes(X);
            Y = ModuloCalculator.Calculate(ModuloCalculator.TWO, X);

            SetMinCryptoAllowed(allowedEncryption);
        }
Beispiel #24
0
        public Peer(string peerId, Uri connectionUri, EncryptionTypes encryption)
        {
            if (peerId == null)
                throw new ArgumentNullException("peerId");
            if (connectionUri == null)
                throw new ArgumentNullException("connectionUri");

            this.connectionUri = connectionUri;
            this.encryption = encryption;
            this.peerId = peerId;
        }
Beispiel #25
0
        private void PeerATest(EncryptionTypes encryption, bool addInitial)
        {
            rig.Engine.Settings.AllowedEncryption = encryption;
            rig.Engine.StartAll();

            HandshakeMessage message = new HandshakeMessage(rig.Manager.InfoHash, "ABC123ABC123ABC123AB", VersionInfo.ProtocolStringV100);

            byte[]          buffer = message.Encode();
            PeerAEncryption a      = new PeerAEncryption(rig.Manager.InfoHash, encryption);

            if (addInitial)
            {
                a.AddPayload(buffer);
            }

            rig.AddConnection(conn.Incoming);
            IAsyncResult result = a.BeginHandshake(conn.Outgoing, null, null);

#if NETSTANDARD1_5
            if (!result.AsyncWaitHandle.WaitOne(4000))
#else
            if (!result.AsyncWaitHandle.WaitOne(4000, true))
#endif
            { Assert.True(false, "Handshake timed out"); }
            a.EndHandshake(result);

            if (!addInitial)
            {
                a.Encryptor.Encrypt(buffer);
                conn.Outgoing.EndSend(conn.Outgoing.BeginSend(buffer, 0, buffer.Length, null, null));
            }

            int received = conn.Outgoing.EndReceive(conn.Outgoing.BeginReceive(buffer, 0, buffer.Length, null, null));
            Assert.True(68 == received, "Recived handshake");

            a.Decryptor.Decrypt(buffer);
            message.Decode(buffer, 0, buffer.Length);
            Assert.Equal(VersionInfo.ProtocolStringV100, message.ProtocolString);

            if (encryption == EncryptionTypes.RC4Full)
            {
                Assert.True(a.Encryptor is RC4);
            }
            else if (encryption == EncryptionTypes.RC4Header)
            {
                Assert.True(a.Encryptor is RC4Header);
            }
            else if (encryption == EncryptionTypes.PlainText)
            {
                Assert.True(a.Encryptor is RC4Header);
            }
        }
Beispiel #26
0
        static async ReusableTask <EncryptorResult> DoCheckIncomingConnectionAsync(IConnection2 connection, EncryptionTypes encryption, EngineSettings settings, InfoHash[] sKeys)
        {
            EncryptionTypes allowedEncryption = (settings?.AllowedEncryption ?? EncryptionTypes.All) & encryption;
            bool            supportsRC4Header = allowedEncryption.HasFlag(EncryptionTypes.RC4Header);
            bool            supportsRC4Full   = allowedEncryption.HasFlag(EncryptionTypes.RC4Full);
            bool            supportsPlainText = allowedEncryption.HasFlag(EncryptionTypes.PlainText);

            // If the connection is incoming, receive the handshake before
            // trying to decide what encryption to use

            var message = new HandshakeMessage();

            using (ClientEngine.BufferPool.Rent(HandshakeMessage.HandshakeLength, out byte[] buffer)) {
Beispiel #27
0
 public EngineSettings(StorageFolder defaultSaveFolder, int listenPort, int globalMaxConnections,
                       int globalHalfOpenConnections, int globalMaxDownloadSpeed, int globalMaxUploadSpeed,
                       EncryptionTypes allowedEncryption)
 {
     GlobalMaxConnections         = globalMaxConnections;
     GlobalMaxDownloadSpeed       = globalMaxDownloadSpeed;
     GlobalMaxUploadSpeed         = globalMaxUploadSpeed;
     GlobalMaxHalfOpenConnections = globalHalfOpenConnections;
     ListenPort            = listenPort;
     AllowedEncryption     = allowedEncryption;
     SaveFolder            = defaultSaveFolder;
     HaveSupressionEnabled = DefaultEnableHaveSupression;
 }
Beispiel #28
0
        private void PeerATest(EncryptionTypes encryption, bool addInitial)
        {
            rig.Engine.Settings.AllowedEncryption = encryption;
            rig.Engine.StartAll();

            var message = new HandshakeMessage(rig.Manager.InfoHash, "ABC123ABC123ABC123AB", VersionInfo.ProtocolStringV100);
            var buffer  = message.Encode();
            var a       = new PeerAEncryption(rig.Manager.InfoHash, encryption);

            if (addInitial)
            {
                a.AddPayload(buffer);
            }

            rig.AddConnection(conn.Incoming);
            var result = a.BeginHandshake(conn.Outgoing, null, null);

            if (!result.AsyncWaitHandle.WaitOne(4000, true))
            {
                Assert.Fail("Handshake timed out");
            }
            a.EndHandshake(result);

            if (!addInitial)
            {
                a.Encryptor.Encrypt(buffer);
                conn.Outgoing.EndSend(conn.Outgoing.BeginSend(buffer, 0, buffer.Length, null, null));
            }

            int received = conn.Outgoing.EndReceive(conn.Outgoing.BeginReceive(buffer, 0, buffer.Length, null, null));

            Assert.AreEqual(68, received, "Recived handshake");

            a.Decryptor.Decrypt(buffer);
            message.Decode(buffer, 0, buffer.Length);
            Assert.AreEqual(VersionInfo.ProtocolStringV100, message.ProtocolString);

            if (encryption == EncryptionTypes.RC4Full)
            {
                Assert.IsInstanceOf <RC4>(a.Encryptor);
            }
            else if (encryption == EncryptionTypes.RC4Header)
            {
                Assert.IsInstanceOf <RC4Header>(a.Encryptor);
            }
            else if (encryption == EncryptionTypes.PlainText)
            {
                Assert.IsInstanceOf <RC4Header>(a.Encryptor);
            }
        }
Beispiel #29
0
        async Task PeerATest(EncryptionTypes encryption, bool addInitial)
        {
            rig.Engine.Settings.AllowedEncryption = encryption;
            await rig.Engine.StartAll();

            HandshakeMessage message = new HandshakeMessage(rig.Manager.InfoHash, "ABC123ABC123ABC123AB", VersionInfo.ProtocolStringV100);

            byte[]          buffer = message.Encode();
            PeerAEncryption a      = new PeerAEncryption(rig.Manager.InfoHash, encryption);

            if (addInitial)
            {
                a.AddPayload(buffer);
            }

            rig.AddConnection(conn.Incoming);
            var result = a.HandshakeAsync(conn.Outgoing);

            if (!result.Wait(4000))
            {
                Assert.Fail("Handshake timed out");
            }

            if (!addInitial)
            {
                a.Encryptor.Encrypt(buffer);
                await conn.Outgoing.SendAsync(buffer, 0, buffer.Length);
            }

            int received = await conn.Outgoing.ReceiveAsync(buffer, 0, buffer.Length);

            Assert.AreEqual(HandshakeMessage.HandshakeLength, received, "Recived handshake");

            a.Decryptor.Decrypt(buffer);
            message.Decode(buffer, 0, buffer.Length);
            Assert.AreEqual(VersionInfo.ProtocolStringV100, message.ProtocolString);

            if (encryption == EncryptionTypes.RC4Full)
            {
                Assert.IsTrue(a.Encryptor is RC4);
            }
            else if (encryption == EncryptionTypes.RC4Header)
            {
                Assert.IsTrue(a.Encryptor is RC4Header);
            }
            else if (encryption == EncryptionTypes.PlainText)
            {
                Assert.IsTrue(a.Encryptor is RC4Header);
            }
        }
Beispiel #30
0
        /// <summary>
        /// The method for encrypt or dncrypt the specified <paramref name="data"/> with <paramref name="password"/>, <paramref name="vector"/>, <paramref name="salt"/>.
        /// </summary>
        /// <param name="type">The type.</param>
        /// <param name="data">The string to be encrypted or decrypted,not null.</param>
        /// <param name="password">The password used to derive the key.</param>
        /// <param name="vector">The initialization vector (IV) to use to derive the key.</param>
        /// <param name="salt">The key salt to use to derive the key.The default is <paramref name="password"/>.</param>
        /// <param name="keySize">The size, in bits, of the secret key used by the symmetric algorithm.</param>
        /// <param name="blockSize">The block size, in bits, of the cryptographic operation.</param>
        /// <param name="encoding">The <see cref="T:System.Text.Encoding"/>,default is <see cref="Encoding.UTF8"/>.</param>
        /// <param name="iterations">The number of iterations for the operation.</param>
        /// <param name="mode">The mode for operation of the symmetric algorithm.</param>
        /// <param name="padding">The padding mode used in the symmetric algorithm. The default is System.Security.Cryptography.PaddingMode.PKCS7.</param>
        /// <returns>The array of <see cref="byte"/> value by <paramref name="type"/>. </returns>
        internal static byte[] EncryptOrDecryptBytes(EncryptionTypes type, string data, string password, string vector = null, string salt = null, int keySize = 128, int blockSize = 128, Encoding encoding = null, int iterations = 1000, CipherMode mode = CipherMode.ECB, PaddingMode padding = PaddingMode.PKCS7)
        {
            ArgumentValidator.Validate(data, password);

            if (encoding == null)
            {
                encoding = Encoding.UTF8;
            }

            return(EncryptOrDecrypt(type,
                                    type == EncryptionTypes.Encrypt ? encoding.GetBytes(data) : Convert.FromBase64String(data),
                                    GetKeyBytes(password, salt, keySize, encoding, iterations),
                                    GetVectorBytes(vector, blockSize, encoding)
                                    , keySize, mode, padding));
        }
Beispiel #31
0
        public Peer(string peerId, Uri connectionUri, EncryptionTypes encryption = EncryptionTypes.All)
        {
            if (peerId == null)
            {
                throw new ArgumentNullException("peerId");
            }
            if (connectionUri == null)
            {
                throw new ArgumentNullException("connectionUri");
            }

            _connectionUri = connectionUri;
            Encryption     = encryption;
            PeerId         = peerId;
        }
        public EncryptedSocket(EncryptionTypes allowedEncryption)
        {
            random = RNGCryptoServiceProvider.Create();
            hasher = HashAlgoFactory.Create <SHA1>();

            GenerateX();
            GenerateY();

            InitialPayload       = BufferManager.EmptyBuffer;
            RemoteInitialPayload = BufferManager.EmptyBuffer;

            bytesReceived = 0;

            SetMinCryptoAllowed(allowedEncryption);
        }
Beispiel #33
0
        private static void HandshakeReceived(bool succeeded, int count, object state)
        {
            EncryptorAsyncResult result     = (EncryptorAsyncResult)state;
            IConnection          connection = result.Id.Connection;

            try
            {
                if (!succeeded)
                {
                    throw new EncryptionException("Couldn't receive the handshake");
                }

                result.Available += count;
                HandshakeMessage message = new HandshakeMessage();
                message.Decode(result.Buffer, 0, result.Buffer.Length);
                bool            valid  = message.ProtocolString == VersionInfo.ProtocolStringV100;
                EncryptionTypes usable = CheckRC4(result.Id);

                bool canUseRC4 = Toolbox.HasEncryption(usable, EncryptionTypes.RC4Header) || Toolbox.HasEncryption(usable, EncryptionTypes.RC4Full);
                // If encryption is disabled and we received an invalid handshake - abort!
                if (valid)
                {
                    result.InitialData = result.Buffer;
                    result.Complete();
                    return;
                }
                if (!canUseRC4 && !valid)
                {
                    result.Complete(new EncryptionException("Invalid handshake received and no decryption works"));
                    return;
                }
                if (canUseRC4)
                {
                    // The data we just received was part of an encrypted handshake and was *not* the BitTorrent handshake
                    result.EncSocket = new PeerBEncryption(result.SKeys, EncryptionTypes.All);
                    result.EncSocket.BeginHandshake(connection, result.Buffer, 0, result.Buffer.Length, CompletedEncryptedHandshakeCallback, result);
                }
                else
                {
                    result.Complete();
                }
            }
            catch (Exception ex)
            {
                result.Complete(ex);
                return;
            }
        }
Beispiel #34
0
        private WaitHandle Announce(Tracker.Tracker tracker, TorrentEvent clientEvent, bool trySubsequent,
                                    ManualResetEvent waitHandle)
        {
            ClientEngine engine = _manager.Engine;

            // If the engine is null, we have been unregistered
            if (engine == null)
            {
                waitHandle.Set();
                return(waitHandle);
            }

            UpdateSucceeded = true;
            LastUpdated     = DateTime.Now;

            EncryptionTypes e = engine.Settings.AllowedEncryption;
            var             requireEncryption  = !Toolbox.HasEncryption(e, EncryptionTypes.PlainText);
            var             supportsEncryption = Toolbox.HasEncryption(e, EncryptionTypes.RC4Full) ||
                                                 Toolbox.HasEncryption(e, EncryptionTypes.RC4Header);

            requireEncryption  = requireEncryption && ClientEngine.SupportsEncryption;
            supportsEncryption = supportsEncryption && ClientEngine.SupportsEncryption;

            IPEndPoint reportedAddress = engine.Settings.ReportedAddress;
            var        ip   = reportedAddress?.Address.ToString();
            int        port = reportedAddress?.Port ?? engine.Listener.Endpoint.Port;

            // FIXME: In metadata mode we need to pretend we need to download data otherwise
            // tracker optimisations might result in no peers being sent back.
            long bytesLeft = 1000;

            if (_manager.HasMetadata)
            {
                bytesLeft = (long)((1 - _manager.Bitfield.PercentComplete / 100.0) * _manager.Torrent.Size);
            }
            var p = new AnnounceParameters(_manager.Monitor.DataBytesDownloaded,
                                           _manager.Monitor.DataBytesUploaded,
                                           bytesLeft,
                                           clientEvent, _infoHash, requireEncryption, _manager.Engine.PeerId,
                                           ip, port)
            {
                SupportsEncryption = supportsEncryption
            };
            var id = new TrackerConnectionID(tracker, trySubsequent, clientEvent, waitHandle);

            tracker.Announce(p, id);
            return(waitHandle);
        }
Beispiel #35
0
        private async Task Announce(ITracker tracker, TorrentEvent clientEvent, bool trySubsequent)
        {
            ClientEngine engine = manager.Engine;

            // If the engine is null, we have been unregistered
            if (engine == null)
            {
                return;
            }

            this.updateSucceeded = true;
            this.lastUpdated     = DateTime.Now;

            EncryptionTypes e = engine.Settings.AllowedEncryption;
            bool            requireEncryption  = !Toolbox.HasEncryption(e, EncryptionTypes.PlainText);
            bool            supportsEncryption = Toolbox.HasEncryption(e, EncryptionTypes.RC4Full) || Toolbox.HasEncryption(e, EncryptionTypes.RC4Header);

            requireEncryption  = requireEncryption && ClientEngine.SupportsEncryption;
            supportsEncryption = supportsEncryption && ClientEngine.SupportsEncryption;

            IPEndPoint reportedAddress = engine.Settings.ReportedAddress;
            string     ip   = reportedAddress == null ? null : reportedAddress.Address.ToString();
            int        port = reportedAddress == null ? engine.Listener.Endpoint.Port : reportedAddress.Port;

            // FIXME: In metadata mode we need to pretend we need to download data otherwise
            // tracker optimisations might result in no peers being sent back.
            long bytesLeft = 1000;

            if (manager.HasMetadata)
            {
                bytesLeft = (long)((1 - this.manager.Bitfield.PercentComplete / 100.0) * this.manager.Torrent.Size);
            }
            AnnounceParameters p = new AnnounceParameters(this.manager.Monitor.DataBytesDownloaded,
                                                          this.manager.Monitor.DataBytesUploaded,
                                                          bytesLeft,
                                                          clientEvent, this.infoHash, requireEncryption, manager.Engine.PeerId,
                                                          ip, port);

            p.SupportsEncryption = supportsEncryption;
            try {
                var peers = await tracker.AnnounceAsync(p);
                await OnAnnounceComplete(tracker, peers, trySubsequent, clientEvent, true);
            } catch {
                await OnAnnounceComplete(tracker, new List <Peer>(), trySubsequent, clientEvent, false);
            }
        }
Beispiel #36
0
        static async ReusableTask <EncryptorResult> DoCheckOutgoingConnectionAsync(IConnection2 connection, EncryptionTypes encryption, EngineSettings settings, InfoHash infoHash, HandshakeMessage handshake)
        {
            EncryptionTypes allowedEncryption = settings.AllowedEncryption & encryption;
            bool            supportsRC4Header = allowedEncryption.HasFlag(EncryptionTypes.RC4Header);
            bool            supportsRC4Full   = allowedEncryption.HasFlag(EncryptionTypes.RC4Full);
            bool            supportsPlainText = allowedEncryption.HasFlag(EncryptionTypes.PlainText);

            if ((settings.PreferEncryption || !supportsPlainText) && (supportsRC4Header || supportsRC4Full))
            {
                // First switch to the threadpool as creating encrypted sockets runs expensive computations in the ctor
                await MainLoop.SwitchToThreadpool();

                var encSocket = new PeerAEncryption(infoHash, allowedEncryption, handshake?.Encode());
                await encSocket.HandshakeAsync(connection).ConfigureAwait(false);

                if (encSocket.Decryptor is RC4Header && !supportsRC4Header)
                {
                    throw new EncryptionException("Decryptor was RC4Header but that is not allowed");
                }
                if (encSocket.Decryptor is RC4 && !supportsRC4Full)
                {
                    throw new EncryptionException("Decryptor was RC4Full but that is not allowed");
                }

                return(new EncryptorResult(encSocket.Decryptor, encSocket.Encryptor, null));
            }
            else if (supportsPlainText)
            {
                if (handshake != null)
                {
                    int    length = handshake.ByteLength;
                    byte[] buffer = ClientEngine.BufferPool.Rent(length);
                    handshake.Encode(buffer, 0);
                    try {
                        await NetworkIO.SendAsync(connection, buffer, 0, length, null, null, null).ConfigureAwait(false);
                    } finally {
                        ClientEngine.BufferPool.Return(buffer);
                    }
                }
                return(new EncryptorResult(PlainTextEncryption.Instance, PlainTextEncryption.Instance, null));
            }

            connection.Dispose();
            throw new EncryptionException("Invalid handshake received and no decryption works");
        }
        public EncryptedSocket(EncryptionTypes allowedEncryption)
        {
            GenerateX();
            GenerateY();

            InitialPayload = BufferManager.EmptyBuffer;
            RemoteInitialPayload = BufferManager.EmptyBuffer;

            _doneSendCallback = DoneSend;
            _doneReceiveCallback = DoneReceive;
            _doneReceiveYCallback = delegate { DoneReceiveY(); };
            _doneSynchronizeCallback = delegate { DoneSynchronize(); };
            _fillSynchronizeBytesCallback = FillSynchronizeBytes;

            _bytesReceived = 0;

            SetMinCryptoAllowed(allowedEncryption);
        }
Beispiel #38
0
 public EngineSettings(string defaultSavePath            = DefaultSavePath, int listenPort = DefaultListenPort,
                       int globalMaxConnections          = DefaultMaxConnections,
                       int globalHalfOpenConnections     = DefaultMaxHalfOpenConnections,
                       int globalMaxDownloadSpeed        = DefaultMaxDownloadSpeed,
                       int globalMaxUploadSpeed          = DefaultMaxUploadSpeed,
                       EncryptionTypes allowedEncryption = DefaultAllowedEncryption,
                       string fastResumePath             = null)
 {
     MaxOpenFiles                 = 15;
     GlobalMaxConnections         = globalMaxConnections;
     GlobalMaxDownloadSpeed       = globalMaxDownloadSpeed;
     GlobalMaxUploadSpeed         = globalMaxUploadSpeed;
     GlobalMaxHalfOpenConnections = globalHalfOpenConnections;
     ListenPort        = listenPort;
     AllowedEncryption = allowedEncryption;
     FastResumePath    = fastResumePath;
     SavePath          = defaultSavePath;
 }
Beispiel #39
0
        protected void SetMinCryptoAllowed(EncryptionTypes allowedEncryption)
        {
            this.allowedEncryption = allowedEncryption;

            // EncryptionType is basically a bit position starting from the right.
            // This sets all bits in CryptoProvide 0 that is to the right of minCryptoAllowed.
            CryptoProvide[0] = CryptoProvide[1] = CryptoProvide[2] = CryptoProvide[3] = 0;

            if (allowedEncryption.HasFlag(EncryptionTypes.RC4Full))
            {
                CryptoProvide[3] |= 1 << 1;
            }

            if (allowedEncryption.HasFlag(EncryptionTypes.RC4Header))
            {
                CryptoProvide[3] |= 1;
            }
        }
        public EncryptedSocket(EncryptionTypes allowedEncryption)
        {
            random = RandomNumberGenerator.Create();
            hasher = HashAlgoFactory.Create<SHA1>();

            GenerateX();
            GenerateY();

            InitialPayload = BufferManager.EmptyBuffer;
            RemoteInitialPayload = BufferManager.EmptyBuffer;

            doneSendCallback = doneSend;
            doneReceiveCallback = doneReceive;
            doneReceiveYCallback = delegate { doneReceiveY(); };
            doneSynchronizeCallback = delegate { doneSynchronize(); };
            fillSynchronizeBytesCallback = fillSynchronizeBytes;

            bytesReceived = 0;

            SetMinCryptoAllowed(allowedEncryption);
        }
        private void PeerATest(EncryptionTypes encryption, bool addInitial)
        {
            rig.Engine.Settings.AllowedEncryption = encryption;
            rig.Engine.StartAll();

            var message = new HandshakeMessage(rig.Manager.InfoHash, "ABC123ABC123ABC123AB",
                VersionInfo.ProtocolStringV100);
            var buffer = message.Encode();
            var a = new PeerAEncryption(rig.Manager.InfoHash, encryption);
            if (addInitial)
                a.AddPayload(buffer);

            rig.AddConnection(conn.Incoming);
            var result = a.BeginHandshake(conn.Outgoing, null, null);
            if (!result.AsyncWaitHandle.WaitOne(4000, true))
                Assert.True(false, "Handshake timed out");
            a.EndHandshake(result);

            if (!addInitial)
            {
                a.Encryptor.Encrypt(buffer);
                conn.Outgoing.EndSend(conn.Outgoing.BeginSend(buffer, 0, buffer.Length, null, null));
            }

            var received = conn.Outgoing.EndReceive(conn.Outgoing.BeginReceive(buffer, 0, buffer.Length, null, null));
            Assert.Equal(68, received);

            a.Decryptor.Decrypt(buffer);
            message.Decode(buffer, 0, buffer.Length);
            Assert.Equal(VersionInfo.ProtocolStringV100, message.ProtocolString);

            if (encryption == EncryptionTypes.RC4Full)
                Assert.True(a.Encryptor is RC4);
            else if (encryption == EncryptionTypes.RC4Header)
                Assert.True(a.Encryptor is RC4Header);
            else if (encryption == EncryptionTypes.PlainText)
                Assert.True(a.Encryptor is RC4Header);
        }
        public static RequestHeader BuildRequestHeader(EncryptionTypes encryptionType, CompressionTypes compressionType, RequestTypes requestType)
        {
            // first create headers
            EncryptionHeader encryptionHeader = new EncryptionHeader()
            {
                EncryptionType = encryptionType
            };

            MessageHeader messageHeader = new MessageHeader()
            {
                CompressionType = compressionType,
                EncryptionHeader = encryptionHeader
            };

            RequestHeader requestHeader = new RequestHeader()
            {
                RequestType = requestType,
                MessageHeader = messageHeader
            };

            // send response header first
            return requestHeader;
        }
        public EngineSettings(string defaultSavePath, int listenPort, int globalMaxConnections, int globalHalfOpenConnections,
			int globalMaxDownloadSpeed, int globalMaxUploadSpeed, EncryptionTypes allowedEncryption)
        {
            this.globalMaxConnections = globalMaxConnections;
            this.globalMaxDownloadSpeed = globalMaxDownloadSpeed;
            this.globalMaxUploadSpeed = globalMaxUploadSpeed;
            globalMaxHalfOpenConnections = globalHalfOpenConnections;
            this.listenPort = listenPort;
            this.allowedEncryption = allowedEncryption;
            savePath = defaultSavePath;
        }
Beispiel #44
0
        private byte[] Y; // 2^X mod P

        #endregion Fields

        #region Constructors

        public EncryptedSocket(EncryptionTypes allowedEncryption)
        {
            random = RNGCryptoServiceProvider.Create();
            hasher = SHA1.Create();

            GenerateX();
            GenerateY();

            InitialPayload = new byte[0];
            RemoteInitialPayload = new byte[0];

            doneSendCallback = doneSend;
            doneReceiveCallback = doneReceive;
            doneReceiveYCallback = delegate { doneReceiveY(); };
            doneSynchronizeCallback = delegate { doneSynchronize(); };
            fillSynchronizeBytesCallback = fillSynchronizeBytes;

            bytesReceived = 0;

            SetMinCryptoAllowed(allowedEncryption);
        }
Beispiel #45
0
 public Encryption(EncryptionTypes type)
 {
     m_EncryptionType = type;
 }
Beispiel #46
0
 /// <summary>
 /// Static encrypt method
 /// </summary>
 public static string EncryptText(string inputText, EncryptionTypes type)
 {
     return new Encryption(type).Encrypt(inputText);
 }
Beispiel #47
0
        private void PeerBTest(EncryptionTypes encryption)
        {
            rig.Engine.Settings.AllowedEncryption = encryption;
            rig.Engine.StartAll();
            rig.AddConnection(conn.Outgoing);

            PeerBEncryption a = new PeerBEncryption(new byte[][] { rig.Manager.Torrent.InfoHash }, EncryptionTypes.All);
            IAsyncResult result = a.BeginHandshake(conn.Incoming, null, null);
            if (!result.AsyncWaitHandle.WaitOne(4000, true))
                Assert.Fail("Handshake timed out");
            a.EndHandshake(result);

            HandshakeMessage message = new HandshakeMessage();
            byte[] buffer = new byte[68];

            conn.Incoming.EndReceive(conn.Incoming.BeginReceive(buffer, 0, buffer.Length, null, null));

            a.Decryptor.Decrypt(buffer);
            message.Decode(buffer, 0, buffer.Length);
            Assert.AreEqual(VersionInfo.ProtocolStringV100, message.ProtocolString);
            if (encryption == EncryptionTypes.RC4Full)
                Assert.IsTrue(a.Encryptor is RC4);
            else if (encryption == EncryptionTypes.RC4Header)
                Assert.IsTrue(a.Encryptor is RC4Header);
            else if (encryption == EncryptionTypes.PlainText)
                Assert.IsTrue(a.Encryptor is RC4Header);
        }
Beispiel #48
0
        private void Handshake(EncryptionTypes encryptionA, EncryptionTypes encryptionB, bool addInitial)
        {
            bool doneA = false;
            bool doneB = false;

            HandshakeMessage m = new HandshakeMessage(rig.Torrent.InfoHash, "12345123451234512345", VersionInfo.ProtocolStringV100);
            byte[] handshake = m.Encode();

            PeerAEncryption a = new PeerAEncryption(rig.Torrent.InfoHash, encryptionA);

            if (addInitial)
                a.AddPayload(handshake);

            PeerBEncryption b = new PeerBEncryption(new byte[][] { rig.Torrent.InfoHash }, encryptionB);

            IAsyncResult resultA = a.BeginHandshake(conn.Outgoing, null, null);
            IAsyncResult resultB = b.BeginHandshake(conn.Incoming, null, null);

            WaitHandle[] handles = new WaitHandle[] { resultA.AsyncWaitHandle, resultB.AsyncWaitHandle };
            int count = 1000;
            while (!WaitHandle.WaitAll(handles, 5, true))
            {
                if (!doneA && (doneA = resultA.IsCompleted))
                    a.EndHandshake(resultA);
                if (!doneB && (doneB = resultB.IsCompleted))
                    b.EndHandshake(resultB);

                if (count-- == 0)
                    Assert.Fail("Could not handshake");
            }
            if (!doneA)
                a.EndHandshake(resultA);
            if (!doneB)
                b.EndHandshake(resultB);

            HandshakeMessage d = new HandshakeMessage();
            if (!addInitial)
            {
                a.Encrypt(handshake, 0, handshake.Length);
                b.Decrypt(handshake, 0, handshake.Length);
                d.Decode(handshake, 0, handshake.Length);
            }
            else
            {
                d.Decode(b.InitialData, 0, b.InitialData.Length);
            }
            Assert.AreEqual(m, d);

            if (encryptionA == EncryptionTypes.RC4Full || encryptionB == EncryptionTypes.RC4Full)
            {
                Assert.IsTrue(a.Encryptor is RC4);
                Assert.IsTrue(b.Encryptor is RC4);
            }
            else if (encryptionA == EncryptionTypes.RC4Header || encryptionB == EncryptionTypes.RC4Header)
            {
                Assert.IsTrue(a.Encryptor is RC4Header);
                Assert.IsTrue(b.Encryptor is RC4Header);
            }
            else if (encryptionA == EncryptionTypes.PlainText || encryptionB == EncryptionTypes.PlainText)
            {
                Assert.IsTrue(a.Encryptor is PlainTextEncryption);
                Assert.IsTrue(b.Encryptor is PlainTextEncryption);
            }
        }
        protected void SetMinCryptoAllowed(EncryptionTypes allowedEncryption)
        {
            this.allowedEncryption = allowedEncryption;

            // EncryptionType is basically a bit position starting from the right.
            // This sets all bits in CryptoProvide 0 that is to the right of minCryptoAllowed.
            CryptoProvide[0] = CryptoProvide[1] = CryptoProvide[2] = CryptoProvide[3] = 0;

            if (Toolbox.HasEncryption(allowedEncryption, EncryptionTypes.RC4Full))
                CryptoProvide[3] |= 1 << 1;

            if (Toolbox.HasEncryption(allowedEncryption, EncryptionTypes.RC4Header))
                CryptoProvide[3] |= 1;
        }
 public EngineSettings(StorageFolder defaultSaveFolder, int listenPort, int globalMaxConnections,
     int globalHalfOpenConnections, int globalMaxDownloadSpeed, int globalMaxUploadSpeed,
     EncryptionTypes allowedEncryption)
 {
     GlobalMaxConnections = globalMaxConnections;
     GlobalMaxDownloadSpeed = globalMaxDownloadSpeed;
     GlobalMaxUploadSpeed = globalMaxUploadSpeed;
     GlobalMaxHalfOpenConnections = globalHalfOpenConnections;
     ListenPort = listenPort;
     AllowedEncryption = allowedEncryption;
     SaveFolder = defaultSaveFolder;
     HaveSupressionEnabled = DefaultEnableHaveSupression;
 }