Example #1
0
 public RpcAnswer(Combinator answer)
 {
     Success = answer.Name != "rpc_error";
     if (Success)
         Combinator = answer;
     else
         Error = new RpcError(answer.Get<int>("error_code"), answer.Get<string>("error_message"));
 }
Example #2
0
        /// <summary>
        /// Обработка входного pq вектора
        /// </summary>
        /// <param name="result">req_DH_params</param>
        /// <returns></returns>
        private Combinator ProcessPqAnswer(Combinator result)
        {
            // Разложение PQ на сомножители
            var        u  = result.Get <byte[]>("pq");
            var        bu = new BigInteger(u); // Входные строки в BE
            BigInteger p  = RhoPollard(bu);
            BigInteger q  = bu / p;

            if (p > q)
            {
                BigInteger max = q;
                q = p;
                p = max;
            }
            // Генерация encrypted data
            // Сформируем запрос p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data
            var nonce       = result.Get <BigInteger>("nonce");
            var serverNonce = result.Get <BigInteger>("server_nonce");

            _newNonce = BigInteger.GenerateRandom(256);

            byte[] beP = p.GetBytes(); // p в BE
            byte[] beQ = q.GetBytes(); // q в BE

            var pQInnerData = new Combinator("p_q_inner_data", u, beP, beQ, nonce, serverNonce, _newNonce);

            if (_nonce != nonce)
            {
                throw new ArgumentException("nonce ответа несовпадает");
            }

            SHA1 sha = SHA1.Create();

            byte[] data = pQInnerData.Serialize();
            byte[] hash = sha.ComputeHash(data);
            byte[] dataWithHash;

            using (var ms = new MemoryStream())
                using (var bw = new BinaryWriter(ms))
                {
                    bw.Write(hash);
                    bw.Write(data);
                    bw.Write(GenerateRandomBytes(255 - bw.BaseStream.Position));
                    dataWithHash = ms.ToArray();
                }

            byte[] encryptedData = RSAEncrypt(dataWithHash);

            var fingerprint = result.Get <Combinator>("server_public_key_fingerprints").Get <long>(0);

            // HACK: отпечаток ключа
            return(new Combinator("req_DH_params", nonce, serverNonce, beP, beQ, fingerprint, encryptedData));
        }
Example #3
0
 public RpcAnswer(Combinator answer)
 {
     Success = answer.Name != "rpc_error";
     if (Success)
     {
         Combinator = answer;
     }
     else
     {
         Error = new RpcError(answer.Get <int>("error_code"), answer.Get <string>("error_message"));
     }
 }
Example #4
0
        private Combinator Unwrap(Combinator response, long responseId, long sessionId, string type)
        {
            switch (response.Name)
            {
            case "gzip_packed":
                byte[] packedData = response.Get <byte[]>("packed_data");
                using (var gz = new GZipStream(new MemoryStream(packedData, 0, packedData.Length), CompressionMode.Decompress, false))
                    response = new Combinator(new BinaryReader(gz).ReadAllBytes(), type);
                return(Unwrap(response, responseId, sessionId, type));

            case "rpc_result":
                if (responseId == sessionId)
                {
                    // выполним распаковку ответа из Object
                    // rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;
                    var raw = response.Get <byte[]>("result");

                    var combinator = new Combinator(raw, type);
                    return(Unwrap(combinator, responseId, sessionId, type));
                }
                Trace.TraceWarning("Unexpected session id: {0}. Actual: {1}. Combinator: {2}", responseId, sessionId, response);
                return(null);

            default:
                return(response);
            }
        }
Example #5
0
        /// <summary>
        /// Генерация клиентского запроса с параметрами Диффи-Хеллмана
        /// </summary>
        /// <param name="serverDh"></param>
        /// <returns></returns>
        private Combinator SetClientDhParams(Combinator serverDh)
        {
            var g       = serverDh.Get <int>("g");
            var dhPrime = serverDh.Get <byte[]>("dh_prime");
            var gA      = serverDh.Get <byte[]>("g_a");

            var dh = new DiffieHellmanManaged(dhPrime, new BigInteger(g).GetBytes(), 2048);

            // generate the public key of the second DH instance
            byte[] gB = dh.CreateKeyExchange();
            // let the second DH instance compute the shared secret using the first DH public key
            _authKey = dh.DecryptKeyExchange(gA);

            // Сформируем ответ
            // отдаем g_b в BE
            var clientDhInnerData = new Combinator("client_DH_inner_data", _nonce, _serverNonce, (long)0, gB);

            byte[] s = clientDhInnerData.Serialize();

            // Шифрование строки
            var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce)
                                           , CalculateTmpAesIV(_newNonce, _serverNonce));

            using (var ms = new MemoryStream())
                using (var bw = new BinaryWriter(ms))
                {
                    SHA1 sha1 = SHA1.Create();
                    bw.Write(sha1.ComputeHash(s));
                    bw.Write(s);

                    var r = new Random();
                    while (bw.BaseStream.Length % 16 != 0)
                    {
                        bw.Write((byte)r.Next());
                    }

                    s = aes.Encrypt(ms.ToArray());
                }

            // Сформируем ответ
            var setClientDhParams = new Combinator("set_client_DH_params", _nonce, _serverNonce, s);

            return(setClientDhParams);
        }
Example #6
0
        /// <summary>
        /// Обработка DH параметров
        /// </summary>
        /// <param name="dhparams"></param>
        /// <returns></returns>
        private Combinator ProcessDhParams(Combinator dhparams)
        {
            var ea = dhparams.Get <byte[]>("encrypted_answer");

            // Обновим server nonce
            _serverNonce = dhparams.Get <BigInteger>("server_nonce");

            // Расшифровка строки
            var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce),
                                           CalculateTmpAesIV(_newNonce, _serverNonce));

            byte[] answerWithHash = aes.Decrypt(ea);
            if (answerWithHash.Length % 16 != 0)
            {
                throw new ArgumentException("Неверный ответ внутри сообщения");
            }

            byte[] answer = answerWithHash.Skip(20).ToArray();

            return(new Combinator(answer, "Server_DH_inner_data"));
        }
Example #7
0
        private void UpdateDifference()
        {
            // updates.getDifference#5b36855a pts:int date:int = updates.Difference;
            RpcAnswer result = RpcCall(new Combinator("updates.getDifference", _updatingState.Pts, _updatingState.Date, _updatingState.Qts));

            // updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
            // updates.difference#8adb0077 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
            // updates.differenceSlice#c5e839b4 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
            if (result.Success)
            {
                Combinator c = result.Combinator;
                switch (c.Name)
                {
                case "updates.differenceEmpty":
                    _updatingState.Update(c);
                    return;

                case "updates.difference":
                    _updatingState.Update(c.Get <Combinator>("state"));
                    break;

                case "updates.differenceSlice":
                    _updatingState.Update(c.Get <Combinator>("intermediate_state"));
                    break;

                default:
                    throw new ArgumentOutOfRangeException(c.Name);
                }

                Difference(c.Get <Combinator>("new_messages"));
                Difference(c.Get <Combinator>("other_updates"));
                Difference(c.Get <Combinator>("chats"));
                Difference(c.Get <Combinator>("users"));
            }
            else
            {
                throw new Exception(result.Error.ToString());
            }
        }
Example #8
0
        private Combinator Unwrap(Combinator response, long responseId, long sessionId, string type)
        {
            switch (response.Name)
            {
                case "gzip_packed":
                    byte[] packedData = response.Get<byte[]>("packed_data");
                    using (var gz = new GZipStream(new MemoryStream(packedData, 0, packedData.Length), CompressionMode.Decompress, false))
                        response = new Combinator(new BinaryReader(gz).ReadAllBytes(), type);
                    return Unwrap(response, responseId, sessionId, type);
                case "rpc_result":
                    if (responseId == sessionId)
                    {
                        // выполним распаковку ответа из Object
                        // rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;
                        var raw = response.Get<byte[]>("result");

                        var combinator = new Combinator(raw, type);
                        return Unwrap(combinator, responseId, sessionId, type);
                    }
                    Trace.TraceWarning("Unexpected session id: {0}. Actual: {1}. Combinator: {2}", responseId, sessionId, response);
                    return null;
                default:
                    return response;
            }
        }
Example #9
0
        /// <summary>
        /// Обработка входного pq вектора
        /// </summary>
        /// <param name="result">req_DH_params</param>
        /// <returns></returns>
        private Combinator ProcessPqAnswer(Combinator result)
        {
            // Разложение PQ на сомножители
            var u = result.Get<byte[]>("pq");
            var bu = new BigInteger(u); // Входные строки в BE
            BigInteger p = RhoPollard(bu);
            BigInteger q = bu / p;
            if (p > q)
            {
                BigInteger max = q;
                q = p;
                p = max;
            }
            // Генерация encrypted data
            // Сформируем запрос p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data
            var nonce = result.Get<BigInteger>("nonce");
            var serverNonce = result.Get<BigInteger>("server_nonce");
            _newNonce = BigInteger.GenerateRandom(256);

            byte[] beP = p.GetBytes(); // p в BE
            byte[] beQ = q.GetBytes(); // q в BE

            var pQInnerData = new Combinator("p_q_inner_data", u, beP, beQ, nonce, serverNonce, _newNonce);

            if (_nonce != nonce)
                throw new ArgumentException("nonce ответа несовпадает");

            SHA1 sha = SHA1.Create();
            byte[] data = pQInnerData.Serialize();
            byte[] hash = sha.ComputeHash(data);
            byte[] dataWithHash;

            using (var ms = new MemoryStream())
            using (var bw = new BinaryWriter(ms))
            {
                bw.Write(hash);
                bw.Write(data);
                bw.Write(GenerateRandomBytes(255 - bw.BaseStream.Position));
                dataWithHash = ms.ToArray();
            }

            byte[] encryptedData = RSAEncrypt(dataWithHash);

            var fingerprint = result.Get<Combinator>("server_public_key_fingerprints").Get<long>(0);

            // HACK: отпечаток ключа
            return new Combinator("req_DH_params", nonce, serverNonce, beP, beQ, fingerprint, encryptedData);
        }
Example #10
0
        /// <summary>
        /// Обработка DH параметров
        /// </summary>
        /// <param name="dhparams"></param>
        /// <returns></returns>
        private Combinator ProcessDhParams(Combinator dhparams)
        {
            var ea = dhparams.Get<byte[]>("encrypted_answer");

            // Обновим server nonce
            _serverNonce = dhparams.Get<BigInteger>("server_nonce");

            // Расшифровка строки
            var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce),
                CalculateTmpAesIV(_newNonce, _serverNonce));

            byte[] answerWithHash = aes.Decrypt(ea);
            if (answerWithHash.Length % 16 != 0)
                throw new ArgumentException("Неверный ответ внутри сообщения");

            byte[] answer = answerWithHash.Skip(20).ToArray();

            return new Combinator(answer, "Server_DH_inner_data");
        }
Example #11
0
        /// <summary>
        /// Генерация клиентского запроса с параметрами Диффи-Хеллмана
        /// </summary>
        /// <param name="serverDh"></param>
        /// <returns></returns>
        private Combinator SetClientDhParams(Combinator serverDh)
        {
            var g = serverDh.Get<int>("g");
            var dhPrime = serverDh.Get<byte[]>("dh_prime");
            var gA = serverDh.Get<byte[]>("g_a");

            var dh = new DiffieHellmanManaged(dhPrime, new BigInteger(g).GetBytes(), 2048);
            // generate the public key of the second DH instance
            byte[] gB = dh.CreateKeyExchange();
            // let the second DH instance compute the shared secret using the first DH public key
            _authKey = dh.DecryptKeyExchange(gA);

            // Сформируем ответ
            // отдаем g_b в BE
            var clientDhInnerData = new Combinator("client_DH_inner_data", _nonce, _serverNonce, (long)0, gB);
            byte[] s = clientDhInnerData.Serialize();

            // Шифрование строки
            var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce)
                , CalculateTmpAesIV(_newNonce, _serverNonce));

            using (var ms = new MemoryStream())
            using (var bw = new BinaryWriter(ms))
            {
                SHA1 sha1 = SHA1.Create();
                bw.Write(sha1.ComputeHash(s));
                bw.Write(s);

                var r = new Random();
                while (bw.BaseStream.Length % 16 != 0)
                    bw.Write((byte)r.Next());

                s = aes.Encrypt(ms.ToArray());
            }

            // Сформируем ответ
            var setClientDhParams = new Combinator("set_client_DH_params", _nonce, _serverNonce, s);

            return setClientDhParams;
        }