Exemplo n.º 1
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
                    });
                }
            }
        }
Exemplo n.º 2
0
        public Step1_Response FromBytes(byte[] bytes)
        {
            var fingerprints = new List <byte[]>();

            using (var memoryStream = new MemoryStream(bytes, false))
            {
                using (var binaryReader = new TBinaryReader(memoryStream))
                {
                    const int responseConstructorNumber = 0x05162463;
                    var       responseCode = binaryReader.ReadInt32();
                    if (responseCode != responseConstructorNumber)
                    {
                        throw new InvalidOperationException($"invalid response code: {responseCode}");
                    }

                    var nonceFromServer = binaryReader.ReadBytes(16);

                    if (!nonceFromServer.SequenceEqual(nonce))
                    {
                        throw new InvalidOperationException("invalid nonce from server");
                    }

                    var serverNonce = binaryReader.ReadBytes(16);

                    byte[] pqbytes = binaryReader.ReadBytes();
                    var    pq      = new BigInteger(1, pqbytes);

                    var       vectorId = binaryReader.ReadInt32();
                    const int vectorConstructorNumber = 0x1cb5c415;
                    if (vectorId != vectorConstructorNumber)
                    {
                        throw new InvalidOperationException($"Invalid vector constructor number {vectorId}");
                    }

                    var fingerprintCount = binaryReader.ReadInt32();
                    for (var i = 0; i < fingerprintCount; i++)
                    {
                        byte[] fingerprint = binaryReader.ReadBytes(8);
                        fingerprints.Add(fingerprint);
                    }

                    return(new Step1_Response
                    {
                        Fingerprints = fingerprints,
                        Nonce = nonce,
                        Pq = pq,
                        ServerNonce = serverNonce
                    });
                }
            }
        }
Exemplo n.º 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);
        }
Exemplo n.º 4
0
        public static Session FromBytes(byte[] buffer, ISessionStore store, string sessionUserId)
        {
            using (var stream = new MemoryStream(buffer))
                using (var reader = new TBinaryReader(stream))
                {
                    var id            = reader.ReadUInt64();
                    var sequence      = reader.ReadInt32();
                    var salt          = reader.ReadUInt64();
                    var lastMessageId = reader.ReadInt64();
                    var timeOffset    = reader.ReadInt32();
                    var serverAddress = reader.ReadString();
                    var port          = reader.ReadInt32();

                    User user = null;
                    if (reader.ReadBoolean())
                    {
                        user = reader.Read <User>();
                    }

                    var authData = reader.ReadBytes();

                    return(new Session(store)
                    {
                        AuthKey = new AuthKey(authData),
                        Id = id,
                        Salt = salt,
                        Sequence = sequence,
                        LastMessageId = lastMessageId,
                        TimeOffset = timeOffset,
                        User = user,
                        SessionUserId = sessionUserId,
                        ServerAddress = serverAddress,
                        Port = port
                    });
                }
        }
Exemplo n.º 5
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);
        }
Exemplo n.º 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);
        }