Exemple #1
0
        private bool HandleContainer(long messageId, int sequence, TBinaryReader messageReader, MTProtoRequest request)
        {
            uint code = messageReader.ReadUInt32();
            int  size = messageReader.ReadInt32();

            for (int i = 0; i < size; i++)
            {
                long innerMessageId = messageReader.ReadInt64();
                int  innerSequence  = messageReader.ReadInt32();
                int  innerLength    = messageReader.ReadInt32();
                long beginPosition  = messageReader.BaseStream.Position;
                try
                {
                    if (!processMessage(innerMessageId, sequence, messageReader, request))
                    {
                        messageReader.BaseStream.Position = beginPosition + innerLength;
                    }
                }
                catch (Exception e)
                {
                    //	logger.error("failed to process message in contailer: {0}", e);
                    messageReader.BaseStream.Position = beginPosition + innerLength;
                }
            }

            return(false);
        }
Exemple #2
0
        public Step2_Response FromBytes(byte[] response)
        {
            byte[] encryptedAnswer;

            using (MemoryStream responseStream = new MemoryStream(response, false))
            {
                using (TBinaryReader responseReader = new TBinaryReader(responseStream))
                {
                    uint responseCode = responseReader.ReadUInt32();

                    if (responseCode == 0x79cb045d)
                    {
                        // server_DH_params_fail
                        throw new InvalidOperationException("server_DH_params_fail: TODO");
                    }

                    if (responseCode != 0xd0e8075c)
                    {
                        throw new InvalidOperationException($"invalid response code: {responseCode}");
                    }

                    byte[] nonceFromServer = responseReader.ReadBytes(16);

                    // TODO:!

                    /*
                     *                  if (!nonceFromServer.SequenceEqual(nonce))
                     *                  {
                     *                          logger.debug("invalid nonce from server");
                     *                          return null;
                     *                  }
                     */


                    byte[] serverNonceFromServer = responseReader.ReadBytes(16);

                    // TODO: !

                    /*
                     *                  if (!serverNonceFromServer.SequenceEqual(serverNonce))
                     *                  {
                     *                          logger.error("invalid server nonce from server");
                     *                          return null;
                     *                  }
                     */

                    encryptedAnswer = responseReader.ReadBytes();

                    return(new Step2_Response()
                    {
                        EncryptedAnswer = encryptedAnswer,
                        ServerNonce = serverNonceFromServer,
                        Nonce = nonceFromServer,
                        NewNonce = newNonce
                    });
                }
            }
        }
Exemple #3
0
        private bool HandleGzipPacked(long messageId, int sequence, TBinaryReader messageReader, MTProtoRequest request)
        {
            uint code = messageReader.ReadUInt32();

            byte[] packedData = GZipStream.UncompressBuffer(messageReader.ReadBytes());
            using (MemoryStream packedStream = new MemoryStream(packedData, false))
                using (TBinaryReader compressedReader = new TBinaryReader(packedStream))
                {
                    processMessage(messageId, sequence, compressedReader, request);
                }

            return(true);
        }
Exemple #4
0
        private bool HandleRpcResult(long messageId, int sequence, TBinaryReader messageReader, MTProtoRequest request)
        {
            uint  code      = messageReader.ReadUInt32();
            ulong requestId = messageReader.ReadUInt64();

            if (requestId == (ulong)request.MessageId)
            {
                request.ConfirmReceived = true;
            }

            //throw new NotImplementedException();

            /*
             *          lock (runningRequests)
             *          {
             *                  if (!runningRequests.ContainsKey(requestId))
             *                  {
             *                          logger.warning("rpc response on unknown request: {0}", requestId);
             *                          messageReader.BaseStream.Position -= 12;
             *                          return false;
             *                  }
             *                  request = runningRequests[requestId];
             *                  runningRequests.Remove(requestId);
             *          }
             */

            uint innerCode = messageReader.ReadUInt32();

            if (innerCode == 0x2144ca19)
            { // rpc_error
                int    errorCode    = messageReader.ReadInt32();
                string errorMessage = messageReader.ReadString();

                if (errorMessage.StartsWith("FLOOD_WAIT_"))
                {
                    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    var seconds      = int.Parse(resultString);
                    Debug.WriteLine($"Should wait {seconds} sec.");
                    Thread.Sleep(1000 * seconds);
                }
                else if (errorMessage.StartsWith("PHONE_MIGRATE_"))
                {
                    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    var dcIdx        = int.Parse(resultString);
                    throw new InvalidOperationException($"Your phone number registered to {dcIdx} dc. Please update settings. See https://github.com/sochix/TeleTurk#i-get-an-error-migrate_x for details.");
                }
                else
                {
                    throw new InvalidOperationException(errorMessage);
                }
            }
            else if (innerCode == 0x3072cfa1)
            {
                // gzip_packed
                byte[] packedData = messageReader.ReadBytes();
                using (MemoryStream packedStream = new MemoryStream(packedData, false))
                    using (System.IO.Compression.GZipStream zipStream = new System.IO.Compression.GZipStream(packedStream, System.IO.Compression.CompressionMode.Decompress))
                        using (TBinaryReader compressedReader = new TBinaryReader(zipStream))
                        {
                            request.OnResponse(compressedReader);
                        }
            }
            else
            {
                messageReader.BaseStream.Position -= 4;

                request.OnResponse(messageReader);
            }

            return(false);
        }
Exemple #5
0
        private bool processMessage(long messageId, int sequence, TBinaryReader messageReader, MTProtoRequest request)
        {
            // TODO: check salt
            // TODO: check sessionid
            // TODO: check seqno

            //logger.debug("processMessage: msg_id {0}, sequence {1}, data {2}", BitConverter.ToString(((MemoryStream)messageReader.BaseStream).GetBuffer(), (int) messageReader.BaseStream.Position, (int) (messageReader.BaseStream.Length - messageReader.BaseStream.Position)).Replace("-","").ToLower());
            needConfirmation.Add(messageId);

            uint code = messageReader.ReadUInt32();

            messageReader.BaseStream.Position -= 4;
            switch (code)
            {
            case 0x73f1f8dc:     // container
                                 //logger.debug("MSG container");
                return(HandleContainer(messageId, sequence, messageReader, request));

            case 0x7abe77ec:     // ping
                                 //logger.debug("MSG ping");
                return(HandlePing(messageId, sequence, messageReader));

            case 0x347773c5:     // pong
                                 //logger.debug("MSG pong");
                return(HandlePong(messageId, sequence, messageReader));

            case 0xae500895:     // future_salts
                                 //logger.debug("MSG future_salts");
                return(HandleFutureSalts(messageId, sequence, messageReader));

            case 0x9ec20908:     // new_session_created
                                 //logger.debug("MSG new_session_created");
                return(HandleNewSessionCreated(messageId, sequence, messageReader));

            case 0x62d6b459:     // msgs_ack
                                 //logger.debug("MSG msds_ack");
                return(HandleMsgsAck(messageId, sequence, messageReader));

            case 0xedab447b:     // bad_server_salt
                                 //logger.debug("MSG bad_server_salt");
                return(HandleBadServerSalt(messageId, sequence, messageReader, request));

            case 0xa7eff811:     // bad_msg_notification
                                 //logger.debug("MSG bad_msg_notification");
                return(HandleBadMsgNotification(messageId, sequence, messageReader));

            case 0x276d3ec6:     // msg_detailed_info
                                 //logger.debug("MSG msg_detailed_info");
                return(HandleMsgDetailedInfo(messageId, sequence, messageReader));

            case 0xf35c6d01:     // rpc_result
                                 //logger.debug("MSG rpc_result");
                return(HandleRpcResult(messageId, sequence, messageReader, request));

            case 0x3072cfa1:     // gzip_packed
                                 //logger.debug("MSG gzip_packed");
                return(HandleGzipPacked(messageId, sequence, messageReader, request));

            case 0xe317af7e:
            case 0xd3f45784:
            case 0x2b2fbd4e:
            case 0x78d4dec1:
            case 0x725b04c3:
            case 0x74ae4240:
                return(HandleUpdate(messageId, sequence, messageReader));

            default:
                //logger.debug("unknown message: {0}", code);
                return(false);
            }
        }
Exemple #6
0
        public byte[] ToBytes(byte[] nonce, byte[] serverNonce, byte[] newNonce, byte[] encryptedAnswer)
        {
            this.newNonce = newNonce;
            AESKeyData key = AES.GenerateKeyDataFromNonces(serverNonce, newNonce);

            byte[] plaintextAnswer = AES.DecryptAES(key, encryptedAnswer);

            // logger.debug("plaintext answer: {0}", BitConverter.ToString(plaintextAnswer));

            int        g;
            BigInteger dhPrime;
            BigInteger ga;

            using (MemoryStream dhInnerData = new MemoryStream(plaintextAnswer))
            {
                using (TBinaryReader dhInnerDataReader = new TBinaryReader(dhInnerData))
                {
                    byte[] hashsum = dhInnerDataReader.ReadBytes(20);
                    uint   code    = dhInnerDataReader.ReadUInt32();
                    if (code != 0xb5890dba)
                    {
                        throw new InvalidOperationException($"invalid dh_inner_data code: {code}");
                    }

                    // logger.debug("valid code");

                    byte[] nonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!nonceFromServer1.SequenceEqual(nonce))
                    {
                        throw new InvalidOperationException("invalid nonce in encrypted answer");
                    }

                    // logger.debug("valid nonce");

                    byte[] serverNonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!serverNonceFromServer1.SequenceEqual(serverNonce))
                    {
                        throw new InvalidOperationException("invalid server nonce in encrypted answer");
                    }

                    // logger.debug("valid server nonce");

                    g       = dhInnerDataReader.ReadInt32();
                    dhPrime = new BigInteger(1, dhInnerDataReader.ReadBytes());
                    ga      = new BigInteger(1, dhInnerDataReader.ReadBytes());

                    int serverTime = dhInnerDataReader.ReadInt32();
                    timeOffset = serverTime - (int)(Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds) / 1000);

                    // logger.debug("g: {0}, dhprime: {1}, ga: {2}", g, dhPrime, ga);
                }
            }

            BigInteger b  = new BigInteger(2048, new Random());
            BigInteger gb = BigInteger.ValueOf(g).ModPow(b, dhPrime);

            _gab = ga.ModPow(b, dhPrime);

            // logger.debug("gab: {0}", gab);

            // prepare client dh inner data
            byte[] clientDHInnerDataBytes;
            using (MemoryStream clientDhInnerData = new MemoryStream())
            {
                using (TBinaryWriter clientDhInnerDataWriter = new TBinaryWriter(clientDhInnerData))
                {
                    clientDhInnerDataWriter.Write(0x6643b654); // client_dh_inner_data
                    clientDhInnerDataWriter.WriteBase(nonce);
                    clientDhInnerDataWriter.WriteBase(serverNonce);
                    clientDhInnerDataWriter.Write((long)0); // TODO: retry_id
                    clientDhInnerDataWriter.Write(gb.ToByteArrayUnsigned());

                    using (MemoryStream clientDhInnerDataWithHash = new MemoryStream())
                    {
                        using (BinaryWriter clientDhInnerDataWithHashWriter = new BinaryWriter(clientDhInnerDataWithHash))
                        {
                            using (SHA1 sha1 = new SHA1Managed())
                            {
                                clientDhInnerDataWithHashWriter.Write(sha1.ComputeHash(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position));
                                clientDhInnerDataWithHashWriter.Write(clientDhInnerData.GetBuffer(), 0, (int)clientDhInnerData.Position);
                                clientDHInnerDataBytes = clientDhInnerDataWithHash.ToArray();
                            }
                        }
                    }
                }
            }

            // logger.debug("client dh inner data papared len {0}: {1}", clientDHInnerDataBytes.Length, BitConverter.ToString(clientDHInnerDataBytes).Replace("-", ""));

            // encryption
            byte[] clientDhInnerDataEncryptedBytes = AES.EncryptAES(key, clientDHInnerDataBytes);

            // logger.debug("inner data encrypted {0}: {1}", clientDhInnerDataEncryptedBytes.Length, BitConverter.ToString(clientDhInnerDataEncryptedBytes).Replace("-", ""));

            // prepare set_client_dh_params
            byte[] setclientDhParamsBytes;
            using (MemoryStream setClientDhParams = new MemoryStream())
            {
                using (TBinaryWriter setClientDhParamsWriter = new TBinaryWriter(setClientDhParams))
                {
                    setClientDhParamsWriter.Write(0xf5045f1f);
                    setClientDhParamsWriter.WriteBase(nonce);
                    setClientDhParamsWriter.WriteBase(serverNonce);
                    setClientDhParamsWriter.Write(clientDhInnerDataEncryptedBytes);

                    setclientDhParamsBytes = setClientDhParams.ToArray();
                }
            }

            // logger.debug("set client dh params prepared: {0}", BitConverter.ToString(setclientDhParamsBytes));

            return(setclientDhParamsBytes);
        }