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); }
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 }); } } }
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); }
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); }
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); } }
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); }