Exemplo n.º 1
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));
        }