Example #1
0
        public static async Task <ResPq> Do(Int128 nonce, MtProtoPlainTransport transport)
        {
            var res = await transport.Call(new ReqPq(nonce)).ConfigureAwait(false);

            Helpers.Assert(res.Nonce == nonce, "auth step1: invalid nonce");
            return(res);
        }
Example #2
0
        public static async Task <Step3Res> Do(
            ServerDhParams.OkTag dhParams,
            Int256 newNonce,
            MtProtoPlainTransport transport
            )
        {
            var key             = Aes.GenerateKeyDataFromNonces(dhParams.ServerNonce.ToBytes(true), newNonce.ToBytes(true));
            var plaintextAnswer = Aes.DecryptAES(key, dhParams.EncryptedAnswer.ToArrayUnsafe());
            var dh = plaintextAnswer.Apply(Deserialize(WithHashSumCheck(ServerDhInnerData.Deserialize)));

            Helpers.Assert(dh.Nonce == dhParams.Nonce, "auth step3: invalid nonce in encrypted answer");
            Helpers.Assert(dh.ServerNonce == dhParams.ServerNonce, "auth step3: invalid server nonce in encrypted answer");

            var currentEpochTime = Helpers.GetCurrentEpochTime();
            var timeOffset       = dh.ServerTime - currentEpochTime;

            var g       = dh.G;
            var dhPrime = new BigInteger(1, dh.DhPrime.ToArrayUnsafe());
            var ga      = new BigInteger(1, dh.Ga.ToArrayUnsafe());

            var b   = new BigInteger(Rnd.NextBytes(2048));
            var gb  = BigInteger.ValueOf(g).ModPow(b, dhPrime);
            var gab = ga.ModPow(b, dhPrime);

            var dhInnerData = new ClientDhInnerData(
                nonce: dh.Nonce,
                serverNonce: dh.ServerNonce,
                retryId: 0,
                gb: gb.ToByteArrayUnsigned().ToBytesUnsafe()
                );
            var dhInnerDataBts = Serialize(dhInnerData);

            var dhInnerDataHashedBts            = WithHashAndPadding(dhInnerDataBts);
            var dhInnerDataHashedEncryptedBytes = Aes.EncryptAES(key, dhInnerDataHashedBts);

            var resp = await transport.Call(new SetClientDhParams(
                                                nonce : dh.Nonce,
                                                serverNonce : dh.ServerNonce,
                                                encryptedData : dhInnerDataHashedEncryptedBytes.ToBytesUnsafe()
                                                )).ConfigureAwait(false);

            var res = resp.Match(
                dhGenOkTag: x => x,
                dhGenFailTag: _ => throw Helpers.FailedAssertion("auth step3: dh_gen_fail"),
                dhGenRetryTag: _ => throw Helpers.FailedAssertion("auth step3: dh_gen_retry")
                );

            var authKey      = AuthKey.FromGab(gab);
            var newNonceHash = authKey.CalcNewNonceHash(newNonce.ToBytes(true), 1).ToInt128();

            Helpers.Assert(res.Nonce == dh.Nonce, "auth step3: invalid nonce");
            Helpers.Assert(res.ServerNonce == dh.ServerNonce, "auth step3: invalid server nonce");
            Helpers.Assert(res.NewNonceHash1 == newNonceHash, "auth step3: invalid new nonce hash");

            return(new Step3Res(authKey, timeOffset));
        }
Example #3
0
        public static async Task <Step3Res> DoAuthentication(MtProtoPlainTransport transport)
        {
            var step1Res = await Step1.Do(BtHelpers.GenNonce16(), transport).ConfigureAwait(false);

            var step2Res = await Step2.Do(step1Res, BtHelpers.GenNonce32(), transport).ConfigureAwait(false);

            var step3Res = await Step3.Do(step2Res.ServerDhParams, step2Res.NewNonce, transport).ConfigureAwait(false);

            return(step3Res);
        }
Example #4
0
        public static async Task <TgConnection> EstablishConnection(
            ILogger logger,
            ConnectInfo connectInfo,
            TgCallMiddlewareChain callMiddlewareChain,
            TcpClientConnectionHandler?connHandler = null
            )
        {
            var endpoint = connectInfo.Endpoint;

            Helpers.Assert(endpoint != null, "endpoint == null");
            var tcpClient = await CreateTcpClient(endpoint !, connHandler).ConfigureAwait(false);

            var tcpTransport = new TcpTransport(tcpClient);

            if (connectInfo.NeedsInAuth)
            {
                var mtPlainTransport = new MtProtoPlainTransport(tcpTransport);
                var result           = await Authenticator.DoAuthentication(mtPlainTransport).ConfigureAwait(false);

                connectInfo.SetAuth(result);
            }

            var session           = connectInfo.ToSession().AsVar();
            var mtCipherTransport = new MtProtoCipherTransport(tcpTransport, session);
            var transport         = new TgCustomizedTransport(new TgTransport(logger, mtCipherTransport, session), callMiddlewareChain);

            // TODO: separate Config
            var config  = new GetConfig();
            var request = new InitConnection <GetConfig, Config>(
                apiId: session.Get().ApiId,
                appVersion: "1.0.0",
                deviceModel: "PC",
                langCode: "en",
                query: config,
                systemVersion: "Win 10.0",
                systemLangCode: "en",
                langPack: "tdesktop",
                proxy: null,
                @params: null
                );
            var invokeWithLayer = new InvokeWithLayer <InitConnection <GetConfig, Config>, Config>(
                layer: SchemeInfo.LayerVersion,
                query: request
                );
            var cfg = await transport.Call(invokeWithLayer).ConfigureAwait(false);

            DcInfoKeeper.Update(cfg);
            return(new TgConnection(session, transport, cfg));
        }
Example #5
0
        public static async Task <Step2Result> Do(ResPq resPq, Int256 newNonce, MtProtoPlainTransport transport)
        {
            var pqBts = resPq.Pq.ToArrayUnsafe();

            Helpers.Assert(pqBts.Length <= 8, "auth step2: pq is too big");
            var pq = new BigInteger(1, pqBts);

            var(pLong, qLong) = Factorizer.Factorize((ulong)pq.LongValue);
            var p = new BigInteger(pLong);
            var q = new BigInteger(qLong);

            var pqInnerData = new PqInnerData.DefaultTag(
                pq: resPq.Pq,
                p: p.ToByteArrayUnsigned().ToBytesUnsafe(),
                q: q.ToByteArrayUnsigned().ToBytesUnsafe(),
                nonce: resPq.Nonce,
                serverNonce: resPq.ServerNonce,
                newNonce: newNonce
                );
            var pqInnerDataBts = Serialize((PqInnerData)pqInnerData);

            var fingerprint = resPq.ServerPublicKeyFingerprints.TryFind(x => x == TgServerRsaKey.Fingerprint)
                              ?? throw Helpers.FailedAssertion(
                                        $"auth step2: can not find a key for fingerprints: {string.Join(", ", resPq.ServerPublicKeyFingerprints.Select(x => x.ToString("x16")))}"
                                        );
            var cipherText = Rsa.Encrypt(TgServerRsaKey.Key, pqInnerDataBts);

            var resp = await transport.Call(new ReqDhParams(
                                                nonce : pqInnerData.Nonce,
                                                serverNonce : pqInnerData.ServerNonce,
                                                p : pqInnerData.P,
                                                q : pqInnerData.Q,
                                                publicKeyFingerprint : fingerprint,
                                                encryptedData : cipherText.ToBytesUnsafe()
                                                )).ConfigureAwait(false);

            var res = resp.Match(
                okTag: x => x,
                failTag: _ => throw Helpers.FailedAssertion("auth step2: server_DH_params_fail")
                );

            Helpers.Assert(res.Nonce == pqInnerData.Nonce, "auth step2: invalid nonce");
            Helpers.Assert(res.ServerNonce == pqInnerData.ServerNonce, "auth step2: invalid server nonce");

            return(new Step2Result(res, newNonce));
        }