Example #1
0
        private static TLObject ParseMessageContainer(BinaryReader reader)
        {
            try
            {
                var RawObject    = new JArray();
                var MessageCount = IntegerUtil.Deserialize(reader);

                for (int i = 0; i < MessageCount; i++)
                {
                    RawObject.Add(new JObject
                    {
                        ["msg_id"] = LongUtil.Deserialize(reader),
                        ["seqno"]  = IntegerUtil.Deserialize(reader),
                        ["bytes"]  = IntegerUtil.Deserialize(reader),
                        ["body"]   = TLObject.Deserialize(reader)
                    });
                }

                return(new TLObject(JObject.FromObject(new
                {
                    _ = "msg_container",
                    messages = RawObject
                })));
            }
            catch
            {
                return(null);
            }
        }
Example #2
0
        /// <summary>
        /// Deserilizes an MTProtoHelper object from a stream
        /// </summary>
        /// <param name="reader">The stream containing the raw MTProtoHelper data</param>
        public static MTProtoHelper Deserialize(BinaryReader reader)
        {
            ServerAuthentication AuthInfo = null;

            if (BoolUtil.Deserialize(reader))
            {
                byte[] AuthInfoKey = null;

                if (BoolUtil.Deserialize(reader))
                {
                    AuthInfoKey = BytesUtil.Deserialize(reader);
                }

                AuthInfo = new ServerAuthentication()
                {
                    AuthKey    = new AuthKey(AuthInfoKey),
                    TimeOffset = IntegerUtil.Deserialize(reader)
                };
            }

            return(new MTProtoHelper(AuthInfo));
        }
Example #3
0
        /// <summary>
        /// Deserilizes a Session object from a stream
        /// </summary>
        /// <param name="reader">The stream containing the raw Session data</param>
        public static Session Deserialize(string FileName, BinaryReader reader)
        {
            Network.MTProtoHelper Helper = null;

            if (BoolUtil.Deserialize(reader))
            {
                Helper = MTProtoHelper.Deserialize(BytesUtil.Deserialize(reader));
            }

            TLObject TLUser = null;

            if (BoolUtil.Deserialize(reader))
            {
                TLUser = TLObject.Deserialize(reader);
            }

            var SessionExpires = IntegerUtil.Deserialize(reader);

            DataCenter DataCenter = null;

            if (BoolUtil.Deserialize(reader))
            {
                DataCenter = DataCenter.Deserialize(BytesUtil.Deserialize(reader));
            }

            var session = new Session(FileName)
            {
                Helper         = Helper,
                TLUser         = TLUser,
                SessionExpires = SessionExpires,
                DataCenter     = DataCenter
            };

            PeerManager.Deserialize(reader).ToList().ForEach(x => session.KnownPeers.AddOrUpdatePeer(x.AsTLObject()));

            return(session);
        }
Example #4
0
        private static TLObject ParseRPCResult(BinaryReader reader)
        {
            try
            {
                ulong LocalMsgID = reader.ReadUInt64();
                uint  RPCCode    = reader.ReadUInt32();

                var RawObject = JObject.FromObject(new
                {
                    _          = "rpc_result",
                    req_msg_id = LocalMsgID
                });

                if (!Enum.IsDefined(typeof(RPCCodes), RPCCode))
                {
                    reader.BaseStream.Position -= 4;
                    RawObject["result"]         = TLObject.Deserialize(reader);
                    return(new TLObject(RawObject));
                }


                switch ((RPCCodes)RPCCode)
                {
                case RPCCodes.rpc_error:
                    RawObject["result"] = JObject.FromObject(new {
                        _             = "rpc_error",
                        error_code    = IntegerUtil.Deserialize(reader),
                        error_message = StringUtil.Read(reader)
                    });

                    //if (errorMessage.StartsWith("FLOOD_WAIT_"))
                    //{
                    //    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    //    var seconds = int.Parse(resultString);
                    //    throw new FloodException(TimeSpan.FromSeconds(seconds));
                    //}
                    //else if (errorMessage.StartsWith("PHONE_MIGRATE_"))
                    //{
                    //    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    //    var dcIdx = int.Parse(resultString);
                    //    throw new PhoneMigrationException(dcIdx);
                    //}
                    //else if (errorMessage.StartsWith("FILE_MIGRATE_"))
                    //{
                    //    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    //    var dcIdx = int.Parse(resultString);
                    //    throw new FileMigrationException(dcIdx);
                    //}
                    //else if (errorMessage.StartsWith("USER_MIGRATE_"))
                    //{
                    //    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    //    var dcIdx = int.Parse(resultString);
                    //    throw new UserMigrationException(dcIdx);
                    //}
                    //else if (errorMessage.StartsWith("NETWORK_MIGRATE_"))
                    //{
                    //    var resultString = Regex.Match(errorMessage, @"\d+").Value;
                    //    var dcIdx = int.Parse(resultString);
                    //    throw new NetworkMigrationException(dcIdx);
                    //}
                    //else if (errorMessage == "AUTH_RESTART")
                    //{
                    //    throw new AuthRestartException("The session is already logged in but is trying to log in again");
                    //}
                    //else if (errorMessage == "PHONE_CODE_INVALID")
                    //{
                    //    throw new InvalidPhoneCodeException("The numeric code used to authenticate does not match the numeric code sent by SMS/Telegram");
                    //}
                    //else if (errorMessage == "SESSION_PASSWORD_NEEDED")
                    //{
                    //    throw new CloudPasswordNeededException("This Account has Cloud Password !");
                    //}
                    //else
                    //{
                    //    throw new InvalidOperationException(errorMessage);
                    //}
                    break;

                case RPCCodes.gzip_packed:
                    RawObject["result"] = JObject.Parse(ParseGZipPacked(reader).ToString());
                    break;

                default:
                    reader.BaseStream.Position -= 4;
                    RawObject["result"]         = JObject.Parse(TLObject.Deserialize(reader).ToString());
                    break;
                }

                return(new TLObject(RawObject));
            }
            catch
            {
                return(null);
            }
        }
Example #5
0
        /// <summary>
        /// Inverse of <see cref="EncryptMessageData"/> for incoming server messages.
        /// </summary>
        public TLObject DecryptMessageData(byte[] body, bool client = false)
        {
            if (body.Length < 8)
            {
                throw new Exception("Cannot decrypt a message of 8 bytes.");
            }

            using (var memory = new MemoryStream(body))
                using (var reader = new BinaryReader(memory))
                    using (var sha = new SHA256Managed())
                    {
                        var serverKeyID = reader.ReadUInt64();
                        if (serverKeyID != AuthInfo.AuthKey.KeyID)
                        {
                            throw new Exception($"Server replied with an invalid auth key: {serverKeyID}");
                        }

                        var MessageKey = reader.ReadBytes(16);

                        (var AES_Key, var AES_ID) = CalcKey(AuthInfo.AuthKey.Key, MessageKey, client);

                        body = AES.DecryptIGE(reader.ReadBytes(body.Length - 24), AES_Key, AES_ID);

                        // https://core.telegram.org/mtproto/security_guidelines
                        // Sections "checking sha256 hash" and "message length"
                        var SHAHash = sha.ComputeHash(AuthInfo.AuthKey.Key
                                                      .Skip(client ? 88 : 96).Take(32)
                                                      .Concat(body)
                                                      .ToArray());

                        var SHASlice = SHAHash.Skip(8).Take(16);

                        if (!SHASlice.SequenceEqual(MessageKey))
                        {
                            throw new Exception("The message key could not be validated.");
                        }
                    }

            TLObject obj = null;

            byte[] RawObject       = null;
            var    remote_msg_id   = -1L;
            var    remote_sequence = -1L;

            using (var memory = new MemoryStream(body))
                using (var reader = new BinaryReader(memory))
                {
                    // The salt could be 0 if we are starting anew and haven't received one yet
                    if (Salt != LongUtil.Deserialize(reader) && Salt != 0)
                    {
                        throw new Exception("The salt could not be validated");
                    }

                    if (ID != LongUtil.Deserialize(reader))
                    {
                        throw new Exception("The session ID could not be validated");
                    }

                    remote_msg_id = LongUtil.Deserialize(reader);
                    // ToDo: Check sequence_number
                    remote_sequence = IntegerUtil.Deserialize(reader);
                    RawObject       = reader.ReadBytes(IntegerUtil.Deserialize(reader));

                    obj = TLObject.Deserialize(RawObject);
                }

            return(new TLObject(JToken.FromObject(new
            {
                _ = "Message",
                msg_id = remote_msg_id,
                seqno = remote_sequence,
                bytes = RawObject,
                body = JToken.Parse(obj.ToString())
            })));
        }