diff --git a/Apps/ClientConsoleApp/Program.cs b/Apps/ClientConsoleApp/Program.cs index 7592860..56a521d 100644 --- a/Apps/ClientConsoleApp/Program.cs +++ b/Apps/ClientConsoleApp/Program.cs @@ -19,10 +19,15 @@ namespace ClientConsoleApp static void Main(string[] args) { - System.Threading.Thread.Sleep(2000); + Thread.Sleep(2000); Console.WriteLine("Hello World!"); - var client = GetTlgClient().Result; + //var tcpClient = new TcpClient(); + //tcpClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000)); + //TestTcpClient(tcpClient); + //TestTcpClient(tcpClient); + + TelegramClient client = GetTlgClient().Result; var normalizedNumber = NumberToSendMessage.StartsWith("+") ? NumberToSendMessage.Substring(1, NumberToSendMessage.Length - 1) : NumberToSendMessage; @@ -86,10 +91,8 @@ namespace ClientConsoleApp } - private static void TestTcpClient() + private static void TestTcpClient(TcpClient tcpClient) { - var tcpClient = new TcpClient(); - tcpClient.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000)); if (tcpClient.Connected) { using (var memoryStream = new MemoryStream()) @@ -108,8 +111,7 @@ namespace ClientConsoleApp } } - System.Threading.Thread.Sleep(20000); - + Thread.Sleep(5000); } } } diff --git a/Apps/TlgListenerApplication/Program.cs b/Apps/TlgListenerApplication/Program.cs index 4c3b859..851fb7a 100644 --- a/Apps/TlgListenerApplication/Program.cs +++ b/Apps/TlgListenerApplication/Program.cs @@ -9,6 +9,7 @@ using System.Text; using System.Threading.Tasks; using Ionic.Crc; using TLSharp.Core.Auth; +using TLSharp.Core.MTProto; using TLSharp.Core.MTProto.Crypto; using TLSharp.Core.Network; using TLSharp.Core.Utils; @@ -59,16 +60,141 @@ namespace TlgListenerApplication } } - - private static void ProcessRequestBySocket(TcpListener tcpListener) + private static void ProcessRequest(TcpListener tcpListener) { - Console.WriteLine("Processing socket..."); - var socketClient = tcpListener.AcceptSocket(); + Console.WriteLine("Processing..."); + var tcpClient = tcpListener.AcceptTcpClient(); + var netStream = tcpClient.GetStream(); + + //var getingCounter = 0; + //while (true) + //{ + // if (!netStream.DataAvailable) + // continue; + // Console.WriteLine("Get data " + ++getingCounter); + //} + + while (tcpClient.Connected) + { + System.Threading.Thread.Sleep(100); + if (!netStream.DataAvailable) continue; + + byte[] nonceFromClient = new byte[16]; + uint responseCode = 0; + const uint step1Constructor = 0x60469778; + const uint step2Constructor = 0xd712e4be; + + if (netStream.CanRead) + { + var bytes = new byte[tcpClient.ReceiveBufferSize]; + netStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize); + var tcpMessage = TcpMessage.Decode(bytes); + var binaryReader = new BinaryReader(new MemoryStream(tcpMessage.Body, false)); + var a = binaryReader.ReadInt64(); + var msgId = binaryReader.ReadInt64(); + var datalength = binaryReader.ReadInt32(); + var data = binaryReader.ReadBytes(datalength); + + var binaryReader2 = new BinaryReader(new MemoryStream(data, false)); + + responseCode = binaryReader2.ReadUInt32(); + Console.WriteLine("Request code: " + responseCode); + if (responseCode == step1Constructor)//---Step1_PQRequest + { + nonceFromClient = binaryReader2.ReadBytes(16); + } + else if (responseCode == step2Constructor)//---Step1_PQRequest + { + nonceFromClient = binaryReader2.ReadBytes(16); + } + + //var obj = new Step1_PQRequest().FromBytes(data); + //var rr = FromByteArray(data); + + //var binaryReader = new BinaryReader(netStream); + //var a = binaryReader.ReadInt64(); + //var b = binaryReader.ReadInt32(); + //var c = binaryReader.ReadInt32(); + //var d = binaryReader.ReadInt32(); + + //Console.WriteLine("This is what the host returned to you: " + returndata); + } + + if (netStream.CanWrite) + { + + var fingerprint = StringToByteArray("216be86c022bb4c3"); + + byte[] outputdata = null; + if (responseCode == step1Constructor) + { + var nonce = new byte[16]; + new Random().NextBytes(nonce); + outputdata = new Step1_Response() + { + Pq = new BigInteger(1, BitConverter.GetBytes(880)), + ServerNonce = nonceFromClient, + Nonce = nonce, + Fingerprints = new List() { fingerprint } + }.ToBytes(); + } + else if (responseCode == step2Constructor) + { + var newnonce = new byte[32]; + new Random().NextBytes(newnonce); + + byte[] answer; + var hashsum = Encoding.UTF8.GetBytes("asdfghjklmnbvcxzasdf"); + const uint innerCode = 0xb5890dba; + AESKeyData key = AES.GenerateKeyDataFromNonces(nonceFromClient, newnonce); + using (var memoryStream = new MemoryStream()) + { + using (var binaryWriter = new BinaryWriter(memoryStream)) + { + binaryWriter.Write(hashsum); + binaryWriter.Write(innerCode); + binaryWriter.Write(nonceFromClient); + binaryWriter.Write(newnonce); + binaryWriter.Write(123456789); + Serializers.Bytes.write(binaryWriter, new BigInteger(1, BitConverter.GetBytes(777)).ToByteArrayUnsigned()); + Serializers.Bytes.write(binaryWriter, new BigInteger(1, BitConverter.GetBytes(888)).ToByteArrayUnsigned()); + answer = memoryStream.ToArray(); + } + } + + outputdata = new Step2_Response() + { + ServerNonce = nonceFromClient, + Nonce = newnonce, + NewNonce = newnonce, + EncryptedAnswer = AES.EncryptAES(key, answer) + }.ToBytes(); + } + + var bytes = PrepareToSend(outputdata); + var datatosend = Encode(bytes, 11); + netStream.Write(datatosend, 0, datatosend.Length); + } + else + { + Console.WriteLine("You cannot write data to this stream."); + tcpClient.Close(); + netStream.Close(); + } + } + } + + private static void ProcessRequestSocket(TcpListener tcpListener) + { + Console.WriteLine("Processing..."); + var tcpClient = tcpListener.AcceptSocket(); + + var bytes = new byte[tcpClient.ReceiveBufferSize]; + var countbyte = tcpClient.Receive(bytes); + + return; byte[] nonceFromClient = new byte[16]; - - var bytes = new byte[socketClient.ReceiveBufferSize]; - socketClient.Receive(bytes); var tcpMessage = TcpMessage.Decode(bytes); var binaryReader = new BinaryReader(new MemoryStream(tcpMessage.Body, false)); var a = binaryReader.ReadInt64(); @@ -89,6 +215,7 @@ namespace TlgListenerApplication new Random().NextBytes(nonce); var fingerprint = StringToByteArray("216be86c022bb4c3"); + //var rr = BitConverter.ToString(fingerprint).Replace("-", ""); var step1 = new Step1_Response() { @@ -97,80 +224,12 @@ namespace TlgListenerApplication Nonce = nonce, Fingerprints = new List() { fingerprint } }; - var bytestosend = PrepareToSend(step1.ToBytes()); - var datatosend = Encode(bytestosend, 11); - socketClient.Send(datatosend); - } + var bytes1 = PrepareToSend(step1.ToBytes()); + var datatosend = Encode(bytes1, 11); + //Byte[] sendBytes = Encoding.UTF8.GetBytes("Is anybody there?"); + tcpClient.Send(datatosend, SocketFlags.Truncated); - private static void ProcessRequest(TcpListener tcpListener) - { - Console.WriteLine("Processing..."); - var tcpClient = tcpListener.AcceptTcpClient(); - - var netStream = tcpClient.GetStream(); - if (netStream.DataAvailable) - { - byte[] nonceFromClient = new byte[16]; - if (netStream.CanRead) - { - var bytes = new byte[tcpClient.ReceiveBufferSize]; - netStream.Read(bytes, 0, (int)tcpClient.ReceiveBufferSize); - var tcpMessage = TcpMessage.Decode(bytes); - var binaryReader = new BinaryReader(new MemoryStream(tcpMessage.Body, false)); - //var a = binaryReader.ReadInt64(); - var msgId = binaryReader.ReadInt64(); - var datalength = binaryReader.ReadInt32(); - var data = binaryReader.ReadBytes(datalength); - - var binaryReader2 = new BinaryReader(new MemoryStream(data, false)); - const int responseConstructorNumber = 0x60469778; - var responseCode = binaryReader2.ReadInt32(); - Console.WriteLine("Request code: " + responseCode); - if (responseCode == responseConstructorNumber)//---Step1_PQRequest - { - nonceFromClient = binaryReader2.ReadBytes(16); - } - - //var obj = new Step1_PQRequest().FromBytes(data); - //var rr = FromByteArray(data); - - //var binaryReader = new BinaryReader(netStream); - //var a = binaryReader.ReadInt64(); - //var b = binaryReader.ReadInt32(); - //var c = binaryReader.ReadInt32(); - //var d = binaryReader.ReadInt32(); - - - //Console.WriteLine("This is what the host returned to you: " + returndata); - } - - if (netStream.CanWrite) - { - var nonce = new byte[16]; - new Random().NextBytes(nonce); - - var fingerprint = StringToByteArray("216be86c022bb4c3"); - //var rr = BitConverter.ToString(fingerprint).Replace("-", ""); - - var step1 = new Step1_Response() - { - Pq = new BigInteger(1, BitConverter.GetBytes(880)), - ServerNonce = nonceFromClient, - Nonce = nonce, - Fingerprints = new List() { fingerprint } - }; - var bytes = PrepareToSend(step1.ToBytes()); - var datatosend = Encode(bytes, 11); - //Byte[] sendBytes = Encoding.UTF8.GetBytes("Is anybody there?"); - netStream.Write(datatosend, 0, datatosend.Length); - } - else - { - Console.WriteLine("You cannot write data to this stream."); - netStream.Close(); - tcpClient.Close(); - } - } + //tcpClient.Close(); } public static async Task Receieve(TcpClient tcpClient) @@ -247,7 +306,7 @@ namespace TlgListenerApplication long newMessageId = ((time / 1000 + timeOffset) << 32) | ((time % 1000) << 22) | (random.Next(524288) << 2); // 2^19 - // [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ] + // [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ] if (lastMessageId >= newMessageId) { diff --git a/TLSharp.Core/Auth/Step2_DHExchange.cs b/TLSharp.Core/Auth/Step2_DHExchange.cs index 53b8016..55bff0d 100644 --- a/TLSharp.Core/Auth/Step2_DHExchange.cs +++ b/TLSharp.Core/Auth/Step2_DHExchange.cs @@ -12,6 +12,25 @@ namespace TLSharp.Core.Auth public byte[] ServerNonce { get; set; } public byte[] NewNonce { get; set; } public byte[] EncryptedAnswer { get; set; } + + public byte[] ToBytes() + { + new Random().NextBytes(Nonce); + const uint constructorNumber = 0xd0e8075c; + + using (var memoryStream = new MemoryStream()) + { + using (var binaryWriter = new BinaryWriter(memoryStream)) + { + binaryWriter.Write(constructorNumber); + binaryWriter.Write(ServerNonce); + binaryWriter.Write(Nonce); + binaryWriter.Write(EncryptedAnswer); + + return memoryStream.ToArray(); + } + } + } } public class Step2_DHExchange @@ -48,7 +67,7 @@ namespace TLSharp.Core.Auth foreach (byte[] fingerprint in fingerprints) { ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty), - pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position); + pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position); if (ciphertext != null) { targetFingerprint = fingerprint; diff --git a/TLSharp.Core/Network/TcpTransport.cs b/TLSharp.Core/Network/TcpTransport.cs index 31bd6b4..4ba997f 100644 --- a/TLSharp.Core/Network/TcpTransport.cs +++ b/TLSharp.Core/Network/TcpTransport.cs @@ -1,89 +1,91 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading.Tasks; - -namespace TLSharp.Core.Network -{ - public delegate TcpClient TcpClientConnectionHandler(string address, int port); - - public class TcpTransport : IDisposable - { - private readonly TcpClient _tcpClient; - private int sendCounter = 0; - - public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null) - { - if (handler == null) - { - _tcpClient = new TcpClient(); - - var ipAddress = IPAddress.Parse(address); - _tcpClient.Connect(ipAddress, port); - } - else - _tcpClient = handler(address, port); - } - - public async Task Send(byte[] packet) - { - if (!_tcpClient.Connected) - throw new InvalidOperationException("Client not connected to server."); - - var tcpMessage = new TcpMessage(sendCounter, packet); - - await _tcpClient.GetStream().WriteAsync(tcpMessage.Encode(), 0, tcpMessage.Encode().Length); - sendCounter++; - } - - public async Task Receieve() - { - var stream = _tcpClient.GetStream(); - - var packetLengthBytes = new byte[4]; - if (await stream.ReadAsync(packetLengthBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the packet length"); - int packetLength = BitConverter.ToInt32(packetLengthBytes, 0); - - var seqBytes = new byte[4]; - if (await stream.ReadAsync(seqBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the sequence"); - int seq = BitConverter.ToInt32(seqBytes, 0); - - int readBytes = 0; - var body = new byte[packetLength - 12]; - int neededToRead = packetLength - 12; - - do - { - var bodyByte = new byte[packetLength - 12]; - var availableBytes = await stream.ReadAsync(bodyByte, 0, neededToRead); - neededToRead -= availableBytes; - Buffer.BlockCopy(bodyByte, 0, body, readBytes, availableBytes); - readBytes += availableBytes; - } - while (readBytes != packetLength - 12); - - var crcBytes = new byte[4]; - if (await stream.ReadAsync(crcBytes, 0, 4) != 4) - throw new InvalidOperationException("Couldn't read the crc"); - int checksum = BitConverter.ToInt32(crcBytes, 0); - - byte[] rv = new byte[packetLengthBytes.Length + seqBytes.Length + body.Length]; - - Buffer.BlockCopy(packetLengthBytes, 0, rv, 0, packetLengthBytes.Length); - Buffer.BlockCopy(seqBytes, 0, rv, packetLengthBytes.Length, seqBytes.Length); - Buffer.BlockCopy(body, 0, rv, packetLengthBytes.Length + seqBytes.Length, body.Length); - var crc32 = new Ionic.Crc.CRC32(); - crc32.SlurpBlock(rv, 0, rv.Length); - var validChecksum = crc32.Crc32Result; - - if (checksum != validChecksum) - { - throw new InvalidOperationException("invalid checksum! skip"); - } - - return new TcpMessage(seq, body); +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading.Tasks; + +namespace TLSharp.Core.Network +{ + public delegate TcpClient TcpClientConnectionHandler(string address, int port); + + public class TcpTransport : IDisposable + { + private readonly TcpClient _tcpClient; + private int sendCounter = 0; + + public TcpTransport(string address, int port, TcpClientConnectionHandler handler = null) + { + if (handler == null) + { + _tcpClient = new TcpClient(); + + _tcpClient.Connect(IPAddress.Parse(address), port); + } + else + _tcpClient = handler(address, port); + } + + public async Task Send(byte[] packet) + { + if (!_tcpClient.Connected) + throw new InvalidOperationException("Client not connected to server."); + + var tcpMessage = new TcpMessage(sendCounter, packet); + + await _tcpClient.GetStream().WriteAsync(tcpMessage.Encode(), 0, tcpMessage.Encode().Length); + sendCounter++; + } + + public async Task Receieve() + { + if (!_tcpClient.Connected) + throw new InvalidOperationException("Client not connected to server."); + + var stream = _tcpClient.GetStream(); + + var packetLengthBytes = new byte[4]; + if (await stream.ReadAsync(packetLengthBytes, 0, 4) != 4) + throw new InvalidOperationException("Couldn't read the packet length"); + int packetLength = BitConverter.ToInt32(packetLengthBytes, 0); + + var seqBytes = new byte[4]; + if (await stream.ReadAsync(seqBytes, 0, 4) != 4) + throw new InvalidOperationException("Couldn't read the sequence"); + int seq = BitConverter.ToInt32(seqBytes, 0); + + int readBytes = 0; + var body = new byte[packetLength - 12]; + int neededToRead = packetLength - 12; + + do + { + var bodyByte = new byte[packetLength - 12]; + var availableBytes = await stream.ReadAsync(bodyByte, 0, neededToRead); + neededToRead -= availableBytes; + Buffer.BlockCopy(bodyByte, 0, body, readBytes, availableBytes); + readBytes += availableBytes; + } + while (readBytes != packetLength - 12); + + var crcBytes = new byte[4]; + if (await stream.ReadAsync(crcBytes, 0, 4) != 4) + throw new InvalidOperationException("Couldn't read the crc"); + int checksum = BitConverter.ToInt32(crcBytes, 0); + + byte[] rv = new byte[packetLengthBytes.Length + seqBytes.Length + body.Length]; + + Buffer.BlockCopy(packetLengthBytes, 0, rv, 0, packetLengthBytes.Length); + Buffer.BlockCopy(seqBytes, 0, rv, packetLengthBytes.Length, seqBytes.Length); + Buffer.BlockCopy(body, 0, rv, packetLengthBytes.Length + seqBytes.Length, body.Length); + var crc32 = new Ionic.Crc.CRC32(); + crc32.SlurpBlock(rv, 0, rv.Length); + var validChecksum = crc32.Crc32Result; + + if (checksum != validChecksum) + { + throw new InvalidOperationException("invalid checksum! skip"); + } + + return new TcpMessage(seq, body); } public bool IsConnected @@ -95,10 +97,10 @@ namespace TLSharp.Core.Network } - public void Dispose() - { - if (_tcpClient.Connected) - _tcpClient.Close(); + public void Dispose() + { + if (_tcpClient.Connected) + _tcpClient.Close(); } - } -} + } +} diff --git a/TLSharp.Core/Session.cs b/TLSharp.Core/Session.cs index 6170dc9..c30d023 100644 --- a/TLSharp.Core/Session.cs +++ b/TLSharp.Core/Session.cs @@ -27,7 +27,7 @@ namespace TLSharp.Core { var sessionFileName = $"{sessionUserId}.dat"; //if (!File.Exists(sessionFileName)) - return null; + return null; using (var stream = new FileStream(sessionFileName, FileMode.Open)) { @@ -54,9 +54,9 @@ namespace TLSharp.Core public class Session { - private const string defaultConnectionAddress = "149.154.175.100";//"149.154.167.50"; + private const string defaultConnectionAddress = "149.154.175.100";//"149.154.167.50"; - private const int defaultConnectionPort = 443; + private const int defaultConnectionPort = 443; public string SessionUserId { get; set; } public string ServerAddress { get; set; } @@ -179,7 +179,7 @@ namespace TLSharp.Core long newMessageId = ((time / 1000 + TimeOffset) << 32) | ((time % 1000) << 22) | (random.Next(524288) << 2); // 2^19 - // [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ] + // [ unix timestamp : 32 bit] [ milliseconds : 10 bit ] [ buffer space : 1 bit ] [ random : 19 bit ] [ msg_id type : 2 bit ] = [ msg_id : 64 bit ] if (LastMessageId >= newMessageId) {