Esempio n. 1
0
        private Tuple <byte[], ulong, int> DecodeMessage(byte[] body)
        {
            byte[] message;
            ulong  remoteMessageId;
            int    remoteSequence;

            using (var inputStream = new MemoryStream(body))
                using (var inputReader = new BinaryReader(inputStream))
                {
                    if (inputReader.BaseStream.Length < 8)
                    {
                        throw new InvalidOperationException($"Can't decode packet");
                    }

                    ulong      remoteAuthKeyId = inputReader.ReadUInt64();  // TODO: check auth key id
                    byte[]     msgKey          = inputReader.ReadBytes(16); // TODO: check msg_key correctness
                    AESKeyData keyData         = Helpers.CalcKey(_session.AuthKey.Data, msgKey, false);

                    byte[] plaintext = AES.DecryptAES(keyData, inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)));

                    using (MemoryStream plaintextStream = new MemoryStream(plaintext))
                        using (BinaryReader plaintextReader = new BinaryReader(plaintextStream))
                        {
                            var remoteSalt      = plaintextReader.ReadUInt64();
                            var remoteSessionId = plaintextReader.ReadUInt64();
                            remoteMessageId = plaintextReader.ReadUInt64();
                            remoteSequence  = plaintextReader.ReadInt32();
                            int msgLen = plaintextReader.ReadInt32();
                            message = plaintextReader.ReadBytes(msgLen);
                        }
                }
            return(new Tuple <byte[], ulong, int>(message, remoteMessageId, remoteSequence));
        }
Esempio n. 2
0
        public override async Task <bool> SendMessage(string message)
        {
            try {
                logger.info("send message with key: {0}", BitConverter.ToString(key).Replace("-", "").ToLower());
                long             messageId = Helpers.GenerateRandomLong();
                DecryptedMessage msg       = TL.decryptedMessage(messageId, Helpers.GenerateRandomBytes(128), message, TL.decryptedMessageMediaEmpty());
                byte[]           data;
                using (MemoryStream memory = new MemoryStream()) {
                    using (BinaryWriter writer = new BinaryWriter(memory)) {
                        msg.Write(writer);
                        data = memory.ToArray();
                    }
                }

                using (MemoryStream memory = new MemoryStream()) {
                    using (BinaryWriter writer = new BinaryWriter(memory)) {
                        writer.Write(data.Length);
                        writer.Write(data);
                        data = memory.ToArray();
                    }
                }

                byte[]     msgKey = Helpers.CalcMsgKey(data);
                AESKeyData aesKey = Helpers.CalcKey(key, msgKey, true);
                data = AES.EncryptAES(aesKey, data);

                using (MemoryStream memory = new MemoryStream()) {
                    using (BinaryWriter writer = new BinaryWriter(memory)) {
                        writer.Write(fingerprint);
                        writer.Write(msgKey);
                        writer.Write(data);
                        data = memory.ToArray();
                    }
                }

                Messages_sentEncryptedMessageConstructor sent = (Messages_sentEncryptedMessageConstructor)await session.Api.messages_sendEncrypted(InputEncryptedChat, messageId, data);

                MessageModel messageModel = new MessageModelEncryptedDelivered(TelegramSession.Instance.SelfId, OpponentId, sent.date, true, true, msg, TL.encryptedFileEmpty());
                messages.Add(messageModel);

                TelegramSession.Instance.Dialogs.Model.UpDialog(this);

                return(true);
            } catch (Exception e) {
                logger.error("send encrypted message exception: {0}", e);
                return(false);
            }
        }
Esempio n. 3
0
        private void GatewayOnInput(object sender, byte[] data)
        {
            ulong remoteSalt;
            ulong remoteSessionId;
            ulong remoteMessageId;
            int   remoteSequence;

            byte[] message;

            using (MemoryStream inputStream = new MemoryStream(data))
                using (BinaryReader inputReader = new BinaryReader(inputStream)) {
                    ulong      remoteAuthKeyId = inputReader.ReadUInt64();  // TODO: check auth key id
                    byte[]     msgKey          = inputReader.ReadBytes(16); // TODO: check msg_key correctness
                    AESKeyData keyData         = Helpers.CalcKey(dc.AuthKey.Data, msgKey, false);

                    byte[] plaintext = AES.DecryptAES(keyData, inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)));

                    using (MemoryStream plaintextStream = new MemoryStream(plaintext))
                        using (BinaryReader plaintextReader = new BinaryReader(plaintextStream)) {
                            remoteSalt      = plaintextReader.ReadUInt64();
                            remoteSessionId = plaintextReader.ReadUInt64();
                            remoteMessageId = plaintextReader.ReadUInt64();
                            remoteSequence  = plaintextReader.ReadInt32();
                            int msgLen = plaintextReader.ReadInt32();
                            message = plaintextReader.ReadBytes(msgLen);
                        }

                    logger.info("gateway on input: {0}", BitConverter.ToString(message).Replace("-", "").ToLower());
                }

            using (MemoryStream messageStream = new MemoryStream(message, false))
                using (BinaryReader messageReader = new BinaryReader(messageStream)) {
                    try {
                        processMessage(remoteMessageId, remoteSequence, messageReader);
                    } catch (Exception e) {
                        logger.error("failed to process message: {0}", e);
                    }
                }
        }
Esempio n. 4
0
        public static byte[] PrepareToSend2(byte[] message, ulong authKeyId, ulong salt, ulong sessionId, ulong messageId, byte[] servernonce, int sequenceNumber, AuthKey authKey)
        {
            using (var memoryStream = new MemoryStream())
            {
                using (var binaryWriter = new BinaryWriter(memoryStream))
                {
                    //binaryWriter.Write(servernonce);
                    binaryWriter.Write(salt);      //salt
                    binaryWriter.Write(sessionId); //sessionId
                    binaryWriter.Write(messageId); //messageid
                    binaryWriter.Write(sequenceNumber);

                    binaryWriter.Write(message.Length);
                    binaryWriter.Write(message);

                    message = memoryStream.ToArray();
                }
            }

            byte[]     msgKey = Helpers.CalcMsgKey(message);
            AESKeyData key    = Helpers.CalcKey(authKey.Data, msgKey, false);

            message = AES.EncryptAES(key, message);

            using (var memoryStream = new MemoryStream())
            {
                using (var binaryWriter = new BinaryWriter(memoryStream))
                {
                    binaryWriter.Write(authKeyId);
                    binaryWriter.Write(msgKey);
                    binaryWriter.Write(message);

                    return(memoryStream.ToArray());
                }
            }
        }
Esempio n. 5
0
        public async Task <(EncryptedData, MemoryStream)> EncryptToStream(Stream stream)
        {
            AES.GenerateIV();
            AES.GenerateKey();

            var msEncrypt = new MemoryStream();

            using (var encryptor = AES.CreateEncryptor())
                using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    await stream.CopyToAsync(csEncrypt);
                }

            var aesKeyData = new AESKeyData {
                IV = AES.IV, Key = AES.Key
            };
            var aesKeyDataBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(aesKeyData));
            var encryptedData   = new EncryptedData
            {
                RSAEncryptedAESKey = RSA.Encrypt(aesKeyDataBytes, RSAEncryptionPadding.Pkcs1)
            };

            return(encryptedData, msEncrypt);
        }
Esempio 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 (BinaryReader dhInnerDataReader = new BinaryReader(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, Serializers.Bytes.read(dhInnerDataReader));
                    ga      = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));

                    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 (BinaryWriter clientDhInnerDataWriter = new BinaryWriter(clientDhInnerData))
                {
                    clientDhInnerDataWriter.Write(0x6643b654); // client_dh_inner_data
                    clientDhInnerDataWriter.Write(nonce);
                    clientDhInnerDataWriter.Write(serverNonce);
                    clientDhInnerDataWriter.Write((long)0); // TODO: retry_id
                    Serializers.Bytes.write(clientDhInnerDataWriter, 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 (BinaryWriter setClientDhParamsWriter = new BinaryWriter(setClientDhParams))
                {
                    setClientDhParamsWriter.Write(0xf5045f1f);
                    setClientDhParamsWriter.Write(nonce);
                    setClientDhParamsWriter.Write(serverNonce);
                    Serializers.Bytes.write(setClientDhParamsWriter, clientDhInnerDataEncryptedBytes);

                    setclientDhParamsBytes = setClientDhParams.ToArray();
                }
            }

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

            return(setclientDhParamsBytes);
        }
Esempio n. 7
0
        public async Task <AuthKey> Generate(TelegramDC dc, int maxRetries)
        {
            ConnectedEvent += delegate {};
            await ConnectAsync(dc, maxRetries);



            random.NextBytes(nonce);

            using (MemoryStream memoryStream = new MemoryStream()) {
                using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream)) {
                    binaryWriter.Write(0x60469778);
                    binaryWriter.Write(nonce);
                    Send(memoryStream.ToArray());
                }
            }

            completionSource = new TaskCompletionSource <byte[]>();
            byte[] response = await completionSource.Task;

            BigInteger    pq;
            List <byte[]> fingerprints = new List <byte[]>();

            using (var memoryStream = new MemoryStream(response, false)) {
                using (var binaryReader = new BinaryReader(memoryStream)) {
                    int responseCode = binaryReader.ReadInt32();
                    if (responseCode != 0x05162463)
                    {
                        logger.error("invalid response code: {0}", responseCode);
                        return(null);
                    }


                    byte[] nonceFromServer = binaryReader.ReadBytes(16);
                    if (!nonceFromServer.SequenceEqual(nonce))
                    {
                        logger.debug("invalid nonce from server");
                        return(null);
                    }


                    serverNonce = binaryReader.ReadBytes(16);

                    byte[] pqbytes = Serializers.Bytes.read(binaryReader);
                    pq = new BigInteger(1, pqbytes);

                    int vectorId = binaryReader.ReadInt32();

                    if (vectorId != 0x1cb5c415)
                    {
                        logger.debug("invalid fingerprints vector id: {0}", vectorId);
                        return(null);
                    }

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

            FactorizedPair pqPair = Factorizator.Factorize(pq);

            logger.debug("stage 1: ok");

            random.NextBytes(newNonce);

            byte[] reqDhParamsBytes;

            using (MemoryStream pqInnerData = new MemoryStream(255)) {
                using (BinaryWriter pqInnerDataWriter = new BinaryWriter(pqInnerData)) {
                    pqInnerDataWriter.Write(0x83c95aec); // pq_inner_data
                    Serializers.Bytes.write(pqInnerDataWriter, pq.ToByteArrayUnsigned());
                    Serializers.Bytes.write(pqInnerDataWriter, pqPair.Min.ToByteArrayUnsigned());
                    Serializers.Bytes.write(pqInnerDataWriter, pqPair.Max.ToByteArrayUnsigned());
                    pqInnerDataWriter.Write(nonce);
                    pqInnerDataWriter.Write(serverNonce);
                    pqInnerDataWriter.Write(newNonce);

                    logger.debug("pq_inner_data: {0}", BitConverter.ToString(pqInnerData.GetBuffer()));

                    byte[] ciphertext        = null;
                    byte[] targetFingerprint = null;
                    foreach (byte[] fingerprint in fingerprints)
                    {
                        ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty),
                                                 pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position);
                        if (ciphertext != null)
                        {
                            targetFingerprint = fingerprint;
                            break;
                        }
                    }

                    if (ciphertext == null)
                    {
                        logger.error("not found valid key for fingerprints: {0}", String.Join(", ", fingerprints));
                        return(null);
                    }

                    using (MemoryStream reqDHParams = new MemoryStream(1024)) {
                        using (BinaryWriter reqDHParamsWriter = new BinaryWriter(reqDHParams)) {
                            reqDHParamsWriter.Write(0xd712e4be); // req_dh_params
                            reqDHParamsWriter.Write(nonce);
                            reqDHParamsWriter.Write(serverNonce);
                            Serializers.Bytes.write(reqDHParamsWriter, pqPair.Min.ToByteArrayUnsigned());
                            Serializers.Bytes.write(reqDHParamsWriter, pqPair.Max.ToByteArrayUnsigned());
                            reqDHParamsWriter.Write(targetFingerprint);
                            Serializers.Bytes.write(reqDHParamsWriter, ciphertext);

                            logger.debug("sending req_dh_paras: {0}", BitConverter.ToString(reqDHParams.ToArray()));
                            reqDhParamsBytes = reqDHParams.ToArray();
                        }
                    }
                }
            }

            completionSource = new TaskCompletionSource <byte[]>();
            Send(reqDhParamsBytes);
            response = await completionSource.Task;

            logger.debug("dh response: {0}", BitConverter.ToString(response));

            byte[] encryptedAnswer;

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

                    if (responseCode == 0x79cb045d)
                    {
                        // server_DH_params_fail
                        logger.error("server_DH_params_fail: TODO");
                        return(null);
                    }

                    if (responseCode != 0xd0e8075c)
                    {
                        logger.error("invalid response code: {0}", responseCode);
                        return(null);
                    }

                    byte[] nonceFromServer = responseReader.ReadBytes(16);
                    if (!nonceFromServer.SequenceEqual(nonce))
                    {
                        logger.debug("invalid nonce from server");
                        return(null);
                    }

                    byte[] serverNonceFromServer = responseReader.ReadBytes(16);
                    if (!serverNonceFromServer.SequenceEqual(serverNonce))
                    {
                        logger.error("invalid server nonce from server");
                        return(null);
                    }

                    encryptedAnswer = Serializers.Bytes.read(responseReader);
                }
            }

            logger.debug("encrypted answer: {0}", BitConverter.ToString(encryptedAnswer));

            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 (BinaryReader dhInnerDataReader = new BinaryReader(dhInnerData)) {
                    byte[] hashsum = dhInnerDataReader.ReadBytes(20);
                    uint   code    = dhInnerDataReader.ReadUInt32();
                    if (code != 0xb5890dba)
                    {
                        logger.error("invalid dh_inner_data code: {0}", code);
                        return(null);
                    }

                    logger.debug("valid code");

                    byte[] nonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!nonceFromServer1.SequenceEqual(nonce))
                    {
                        logger.error("invalid nonce in encrypted answer");
                        return(null);
                    }

                    logger.debug("valid nonce");

                    byte[] serverNonceFromServer1 = dhInnerDataReader.ReadBytes(16);
                    if (!serverNonceFromServer1.SequenceEqual(serverNonce))
                    {
                        logger.error("invalid server nonce in encrypted answer");
                        return(null);
                    }

                    logger.debug("valid server nonce");

                    g       = dhInnerDataReader.ReadInt32();
                    dhPrime = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));
                    ga      = new BigInteger(1, Serializers.Bytes.read(dhInnerDataReader));

                    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, random);
            BigInteger gb  = BigInteger.ValueOf(g).ModPow(b, dhPrime);
            BigInteger gab = ga.ModPow(b, dhPrime);

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

            // prepare client dh inner data
            byte[] clientDHInnerDataBytes;
            using (MemoryStream clientDhInnerData = new MemoryStream()) {
                using (BinaryWriter clientDhInnerDataWriter = new BinaryWriter(clientDhInnerData)) {
                    clientDhInnerDataWriter.Write(0x6643b654); // client_dh_inner_data
                    clientDhInnerDataWriter.Write(nonce);
                    clientDhInnerDataWriter.Write(serverNonce);
                    clientDhInnerDataWriter.Write((long)0);  // TODO: retry_id
                    Serializers.Bytes.write(clientDhInnerDataWriter, 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 (BinaryWriter setClientDhParamsWriter = new BinaryWriter(setClientDhParams)) {
                    setClientDhParamsWriter.Write(0xf5045f1f);
                    setClientDhParamsWriter.Write(nonce);
                    setClientDhParamsWriter.Write(serverNonce);
                    Serializers.Bytes.write(setClientDhParamsWriter, clientDhInnerDataEncryptedBytes);

                    setclientDhParamsBytes = setClientDhParams.ToArray();
                }
            }

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


            completionSource = new TaskCompletionSource <byte[]>();
            Send(setclientDhParamsBytes);
            response = await completionSource.Task;

            using (MemoryStream responseStream = new MemoryStream(response)) {
                using (BinaryReader responseReader = new BinaryReader(responseStream)) {
                    uint code = responseReader.ReadUInt32();
                    if (code == 0x3bcbf734)  // dh_gen_ok
                    {
                        logger.debug("dh_gen_ok");

                        byte[] nonceFromServer = responseReader.ReadBytes(16);
                        if (!nonceFromServer.SequenceEqual(nonce))
                        {
                            logger.error("invalid nonce");
                            return(null);
                        }

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

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

                        byte[] newNonceHash1 = responseReader.ReadBytes(16);
                        logger.debug("new nonce hash 1: {0}", BitConverter.ToString(newNonceHash1));

                        AuthKey authKey = new AuthKey(gab);

                        byte[] newNonceHashCalculated = authKey.CalcNewNonceHash(newNonce, 1);

                        if (!newNonceHash1.SequenceEqual(newNonceHashCalculated))
                        {
                            logger.error("invalid new nonce hash");
                            return(null);
                        }

                        logger.info("generated new auth key: {0}", gab);
                        logger.info("saving time offset: {0}", timeOffset);
                        TelegramSession.Instance.TimeOffset = timeOffset;
                        return(authKey);
                    }
                    else if (code == 0x46dc1fb9)  // dh_gen_retry
                    {
                        logger.debug("dh_gen_retry");
                        return(null);
                    }
                    else if (code == 0xa69dae02)
                    {
                        // dh_gen_fail
                        logger.debug("dh_gen_fail");
                        return(null);
                    }
                    else
                    {
                        logger.debug("dh_gen unknown: {0}", code);
                        return(null);
                    }
                }
            }
        }
Esempio n. 8
0
        // in background thread
        public void ReceiveMessage(EncryptedMessage encryptedMessage)
        {
            try {
                if (encryptedMessage.Constructor == Constructor.encryptedMessage)
                {
                    logger.info("simple encrypted message");
                    EncryptedMessageConstructor encryptedMessageConstructor = (EncryptedMessageConstructor)encryptedMessage;
                    byte[] data = encryptedMessageConstructor.bytes;
                    byte[] msgKey;
                    long   keyFingerprint;

                    logger.info("encrypted message data: {0}", BitConverter.ToString(data).Replace("-", "").ToLower());

                    using (MemoryStream memory = new MemoryStream(data)) {
                        using (BinaryReader reader = new BinaryReader(memory)) {
                            keyFingerprint = reader.ReadInt64();
                            msgKey         = reader.ReadBytes(16);
                            data           = reader.ReadBytes(data.Length - 16 - 8);
                        }
                    }

                    if (fingerprint != keyFingerprint)
                    {
                        logger.error("invalid key fingerprint");
                        return;
                    }

                    logger.info("ciphertext data: {0}", BitConverter.ToString(data).Replace("-", "").ToLower());

                    AESKeyData aesKey = Helpers.CalcKey(key, msgKey, true);
                    data = AES.DecryptAES(aesKey, data);
                    byte[] data2 = AES.EncryptAES(aesKey, data);
                    byte[] data3 = AES.DecryptAES(aesKey, data2);

                    logger.info("aes equals: {0}", data.SequenceEqual(data3));

                    logger.info("plaintext data: {0}", BitConverter.ToString(data).Replace("-", "").ToLower());
                    logger.info("two-transformed plaintext: {0}", BitConverter.ToString(data3).Replace("-", "").ToLower());

                    byte[] calculatedMsgKey;

                    using (MemoryStream memory = new MemoryStream(data)) {
                        using (BinaryReader reader = new BinaryReader(memory)) {
                            int len = reader.ReadInt32();
                            logger.info("readed len = {0}, actual len = {1}", len, data.Length - 4);
                            if (len < 0 || len > data.Length - 4)
                            {
                                return;
                            }
                            calculatedMsgKey = Helpers.CalcMsgKey(data, 0, 4 + len);
                            data             = reader.ReadBytes(len);
                        }
                    }

                    if (!msgKey.SequenceEqual(calculatedMsgKey))
                    {
                        logger.info("incalid msg key: data {0}, sha1 {1}, received msg key {2}", BitConverter.ToString(data), BitConverter.ToString(Helpers.sha1(data)), BitConverter.ToString(msgKey));
                        return;
                    }

                    DecryptedMessage decryptedMessage;

                    using (MemoryStream memory = new MemoryStream(data)) {
                        using (BinaryReader reader = new BinaryReader(memory)) {
                            //DecryptedMessageLayerConstructor layer = (DecryptedMessageLayerConstructor) TL.Parse<DecryptedMessageLayer>(reader);
//                            if(layer.layer > 8) {
//                                logger.info("encrypted message layer {0} - need upgrade", layer.layer);
//                                // TODO: notify - need upgrade
//                                return;
//                            }

                            decryptedMessage = TL.Parse <DecryptedMessage>(reader);
                        }
                    }



                    logger.info("decrypted message: {0}", decryptedMessage);

                    if (decryptedMessage.Constructor == Constructor.decryptedMessageService)
                    {
                        DecryptedMessageAction action = ((DecryptedMessageServiceConstructor)decryptedMessage).action;
                        if (action.Constructor == Constructor.decryptedMessageActionSetMessageTTL)
                        {
                            DecryptedMessageActionSetMessageTTLConstructor actionttl = (DecryptedMessageActionSetMessageTTLConstructor)action;
                            UpdateTTL(actionttl.ttl_seconds);
                        }
                    }

                    MessageModel messageModel = new MessageModelEncryptedDelivered(OpponentId, TelegramSession.Instance.SelfId, encryptedMessageConstructor.date, false, true, decryptedMessage, encryptedMessageConstructor.file);

                    Deployment.Current.Dispatcher.BeginInvoke(() => {
                        messages.Add(messageModel);

                        if (this == TelegramSession.Instance.Dialogs.OpenedDialog)
                        {
                            OpenedRead();
                        }
                    });
                }
            } catch (Exception e) {
                logger.error("dialog model receive encrypted message exception: {0}", e);
            }
        }
Esempio n. 9
0
        private static void ProcessRequest(TcpListener tcpListener)
        {
            Console.WriteLine("Processing...");
            var        tcpClient = tcpListener.AcceptTcpClient();
            var        netStream = tcpClient.GetStream();
            BigInteger ga        = null;

            byte[]     newNonce       = new byte[32];
            BigInteger a              = new BigInteger(2048, new Random());
            var        dhPrime        = new BigInteger("00C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F91F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD15A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F", 16);
            BigInteger gb             = null;
            var        sequenceNumber = 1;
            ulong?     messageId      = null;
            var        privateKey     = new BigInteger("582A4D5EE3A45C1AEEBDECD549D1FD4E12337B05C4C0A03FA8FF4A0A7B2861BAB86E8B58A70AAB9CF173FA313348239E28B17D34C7CEC8B68544BAD8623A306D747B7DC1D3D064FA73CE96893E8AFC36F7CDF58A383F48BDEC284D30BFFBC3F1A413DC869B3692EDD26004EE661C021BDA32F124D6631C67891E3E35EEDEAA08BFED8DBB7A6CC1D550CF16C67703BBDFFF0500FD81A55F98D92ECD67CE3CC31B766EA0DFBA284E18677E46036D9ED04105AAD11E97FD675F49A3B54D5AD395AA3C5B8343CDFF70C2E2A9243A47FBC5F541BBAE910B5DD1BF574B1E732A105C2B8F5239A4DFA0BCE0559F18BA0C44D31A279FA7CDCA612BD8F9796EBD114F7FA9", 16);
            AuthKey    authKey        = null;

            //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];
                byte[] servernonce     = new byte[16];

                uint responseCode  = 0;
                int  innerCode     = 0;
                long authkeysample = 123456789;

                const long step1Constructor = 0x60469778;
                const long step2Constructor = 0xd712e4be;
                const long step3Constructor = 0xf5045f1f;

                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 authKeyId = binaryReader.ReadInt64();
                    if (authKeyId == 0)
                    {
                        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);
                            servernonce     = binaryReader2.ReadBytes(16);
                            var p = binaryReader2.ReadBytes(4);
                            var q = binaryReader2.ReadBytes(8);
                            var targetFingerprint = BitConverter.ToString(binaryReader2.ReadBytes(8)).Replace("-", string.Empty);

                            //TODO: need to decryption
                            var ciphertext = Bytes.read(binaryReader2);
                            ciphertext = RSA.Decrypt(targetFingerprint, ciphertext, privateKey, 0, ciphertext.Length);
                            var cipherReader    = new BinaryReader(new MemoryStream(ciphertext, false));
                            var hashsum         = cipherReader.ReadBytes(20);
                            var innercode       = cipherReader.ReadUInt32();//0x83c95aec
                            var pq              = cipherReader.ReadBytes(20);
                            var noncetemp       = cipherReader.ReadBytes(16);
                            var servernoncetemp = cipherReader.ReadBytes(16);
                            newNonce = cipherReader.ReadBytes(32);
                            //Array.Copy(ciphertext, ciphertext.Length - 32, newNonce, 0, 32);
                            //ciphertext.CopyTo(newnoncetemp, ciphertext.Length - 32);
                        }
                        else if (responseCode == step3Constructor) //---Step1_PQRequest
                        {
                            nonceFromClient = binaryReader2.ReadBytes(16);
                            servernonce     = binaryReader2.ReadBytes(16);

                            //TODO: need to decryption
                            var        ciphertext                = Bytes.read(binaryReader2);
                            AESKeyData key                       = AES.GenerateKeyDataFromNonces(servernonce, newNonce);
                            var        cleartext                 = AES.DecryptAES(key, ciphertext);
                            var        binaryReadernner          = new BinaryReader(new MemoryStream(cleartext, false));
                            var        hasheddata                = binaryReadernner.ReadBytes(20);
                            var        client_dh_inner_data_code = binaryReadernner.ReadUInt32();
                            if (client_dh_inner_data_code != 0x6643b654)
                            {
                                throw new Exception("We have a complex story");
                            }
                            var nonceFromClient_temp = binaryReadernner.ReadBytes(16);
                            var servernonce_temp     = binaryReadernner.ReadBytes(16);
                            var zero = binaryReadernner.ReadUInt64();
                            gb = new BigInteger(Bytes.read(binaryReadernner));
                        }
                    }
                    else
                    {
                        var _gba = gb.ModPow(a, dhPrime);
                        authKey = new AuthKey(_gba);
                        var decodeMessage = DecodeMessage(tcpMessage.Body, authKey);
                        var objrawReader  = new BinaryReader(new MemoryStream(decodeMessage.Item1, false));
                        messageId = decodeMessage.Item2;
                        innerCode = objrawReader.ReadInt32();


                        if (innerCode == 0x62d6b459)//acknowledged
                        {
                            var vector   = objrawReader.ReadInt32();
                            var msgCount = objrawReader.ReadInt32();
                            continue;
                        }
                        else //if (responseCode == -627372787)
                        {
                            objrawReader.BaseStream.Position += -4;
                            var obj = ObjectUtils.DeserializeObject(objrawReader);
                            if (obj is TLRequestInvokeWithLayer)
                            {
                                var invokewithlayer = (TLRequestInvokeWithLayer)obj;
                                if (invokewithlayer.Query is TLRequestInitConnection)
                                {
                                    var requestInitConnection = (TLRequestInitConnection)invokewithlayer.Query;
                                }
                                else if (invokewithlayer.Query is TLRequestSendCode)
                                {
                                    var requestSendCode = (TLRequestSendCode)invokewithlayer.Query;
                                }
                            }
                            else if (obj is TLRequestSendCode)
                            {
                                var requestSendCode = (TLRequestSendCode)obj;
                            }
                            else if (obj is TLRequestSignIn)
                            {
                                var requestSignIn = (TLRequestSignIn)obj;
                            }
                            else if (obj is TLRequestGetContacts)
                            {
                                var requestGetContacts = (TLRequestGetContacts)obj;
                            }
                        }

                        //var keyData = Helpers.CalcKey(buffer, messageKey, false);
                        //var data = AES.DecryptAES(keyData, buffer);
                    }
                }

                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 <byte[]>()
                            {
                                fingerprint
                            }
                        }.ToBytes();
                    }
                    else if (responseCode == step2Constructor)
                    {
                        //var nonce = new byte[16];
                        //new Random().NextBytes(nonce);

                        byte[]     answer;
                        var        hashsum       = Encoding.UTF8.GetBytes("asdfghjklmnbvcxzasdf");
                        const uint innerCodetemp = 0xb5890dba;
                        AESKeyData key           = AES.GenerateKeyDataFromNonces(servernonce, newNonce);

                        var g = 47;
                        ga = BigInteger.ValueOf(g).ModPow(a, dhPrime);

                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(hashsum);
                                binaryWriter.Write(innerCodetemp);
                                binaryWriter.Write(nonceFromClient);
                                binaryWriter.Write(servernonce);
                                binaryWriter.Write(g);
                                Bytes.write(binaryWriter, dhPrime.ToByteArrayUnsigned());
                                Bytes.write(binaryWriter, ga.ToByteArrayUnsigned());
                                Bytes.write(binaryWriter, BitConverter.GetBytes((int)(Convert.ToInt64((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds) / 1000)));//server datetime
                                answer = memoryStream.ToArray();
                            }
                        }

                        outputdata = new Step2_Response()
                        {
                            ServerNonce     = nonceFromClient,
                            Nonce           = servernonce,
                            NewNonce        = newNonce,
                            EncryptedAnswer = AES.EncryptAES(key, answer)
                        }.ToBytes();
                    }
                    else if (responseCode == step3Constructor)
                    {
                        var _gba = gb.ModPow(a, dhPrime);
                        authKey = new AuthKey(_gba);
                        var        newNonceHash  = authKey.CalcNewNonceHash(newNonce, 1);
                        const uint innerCodeTemp = 0x3bcbf734;
                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(innerCodeTemp);
                                binaryWriter.Write(servernonce);
                                binaryWriter.Write(nonceFromClient);
                                binaryWriter.Write(newNonceHash);//hashnewnonce
                                outputdata = memoryStream.ToArray();
                            }
                        }
                    }
                    else if (innerCode == -2035355412)//TLRequestSendCode
                    {
                        #region Generate TLSentCode

                        var sentCode = new TLSentCode();
                        sentCode.PhoneRegistered = false;
                        sentCode.Timeout         = 7777;
                        sentCode.PhoneCodeHash   = "asdfghjklmnbvcxzasdf";
                        sentCode.Flags           = 3;
                        sentCode.NextType        = new TLCodeTypeSms();
                        sentCode.Type            = new TLSentCodeTypeApp()
                        {
                            Length = 20
                        };

                        #endregion

                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(0xf35c6d01);      //main code
                                binaryWriter.Write(messageId.Value); //requestId -- ulong -- from mesage id
                                sentCode.SerializeBody(binaryWriter);
                                outputdata = memoryStream.ToArray();
                            }
                        }
                    }
                    else if (innerCode == -627372787)
                    {
                        #region Generate TLConfig
                        //---Genrate mock tlconfig
                        var config = new TLConfig();
                        config.CallConnectTimeoutMs = 7777;
                        config.CallPacketTimeoutMs  = 7777;
                        config.CallReceiveTimeoutMs = 7777;
                        config.CallRingTimeoutMs    = 7777;
                        config.ChatBigSize          = 7777;
                        config.ChatSizeMax          = 777;
                        config.Date      = Convert.ToInt32((DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds);
                        config.DcOptions = new TLVector <TLDcOption>()
                        {
                            new TLDcOption()
                            {
                                Flags = 0, Id = 1, IpAddress = "127.0.0.1", Port = 5000
                            }
                        };
                        config.DisabledFeatures      = new TLVector <TLDisabledFeature>();
                        config.ForwardedCountMax     = 777;
                        config.MegagroupSizeMax      = 777;
                        config.NotifyCloudDelayMs    = 7777;
                        config.NotifyDefaultDelayMs  = 7777;
                        config.OfflineBlurTimeoutMs  = 7777;
                        config.OfflineIdleTimeoutMs  = 7777;
                        config.OnlineCloudTimeoutMs  = 7777;
                        config.OnlineUpdatePeriodMs  = 7777;
                        config.PhonecallsEnabled     = false;
                        config.PinnedDialogsCountMax = 7;
                        config.PushChatLimit         = 7;
                        config.PushChatPeriodMs      = 777;
                        config.RatingEDecay          = 777;
                        config.SavedGifsLimit        = 777;
                        config.StickersRecentLimit   = 777;
                        config.ThisDc      = 1;//TODO: ---what's this?!---
                        config.MeUrlPrefix = "https://t.me/";
                        config.TestMode    = false;
                        #endregion

                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(0xf35c6d01);      //main code
                                                                     //binaryWriter.Write(0xf35c6d02);//code
                                binaryWriter.Write(messageId.Value); //requestId -- ulong -- from mesage id
                                                                     //binaryWriter.Write(0x2144ca17);//innercode -- int
                                                                     //binaryWriter.Write(1123456789);//sample code
                                                                     //Serializers.Bytes.write(binaryWriter, config.Serialize());
                                config.SerializeBody(binaryWriter);
                                outputdata = memoryStream.ToArray();
                            }
                        }
                    }
                    else if (innerCode == -1126886015)
                    {
                        #region Generate TLAuthorization

                        var auth = new TeleSharp.TL.Auth.TLAuthorization();
                        auth.Flags = 3;
                        auth.User  = new TLUser()
                        {
                            FirstName = "Meysami"
                        };

                        #endregion

                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(0xf35c6d01);      //main code
                                binaryWriter.Write(messageId.Value); //requestId -- ulong -- from mesage id
                                auth.SerializeBody(binaryWriter);
                                outputdata = memoryStream.ToArray();
                            }
                        }
                    }
                    else if (innerCode == 583445000)//GetContacts
                    {
                        #region Generate TLAbsContacts

                        var contacts = new TLContacts();
                        contacts.Contacts = new TLVector <TLContact>()
                        {
                            new TLContact()
                            {
                                UserId = 11
                            },
                            new TLContact()
                            {
                                UserId = 12
                            }
                        };
                        contacts.Users = new TLVector <TLAbsUser>()
                        {
                            new TLUser()
                            {
                                Bot = false, FirstName = "Mary", Id = 11
                            },
                            new TLUser()
                            {
                                Bot = false, FirstName = "Mary 2", Id = 12
                            }
                        };

                        #endregion

                        using (var memoryStream = new MemoryStream())
                        {
                            using (var binaryWriter = new BinaryWriter(memoryStream))
                            {
                                binaryWriter.Write(0xf35c6d01);      //main code
                                binaryWriter.Write(messageId.Value); //requestId -- ulong -- from mesage id
                                contacts.SerializeBody(binaryWriter);
                                outputdata = memoryStream.ToArray();
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }

                    if (innerCode != 0)
                    {
                        outputdata = PrepareToSend2(outputdata, authKey.Id, 0, 0, 0, servernonce, sequenceNumber, authKey);
                    }
                    else
                    {
                        outputdata = PrepareToSend(outputdata);
                    }

                    outputdata = Encode(outputdata, sequenceNumber++);
                    netStream.Write(outputdata, 0, outputdata.Length);
                }
                else
                {
                    Console.WriteLine("You cannot write data to this stream.");
                    tcpClient.Close();
                    netStream.Close();
                }
            }
        }