Esempio n. 1
0
        private static TLPQInnerData GetInnerData(TLInt dcId, TLResPQ resPQ, TLInt256 newNonce, out TimeSpan calcTime, out WindowsPhone.Tuple <ulong, ulong> pqPair)
        {
            var pq = BitConverter.ToUInt64(resPQ.PQ.Data.Reverse().ToArray(), 0);

            TLUtils.WriteLine("pq: " + pq);

            var pqCalcTime = Stopwatch.StartNew();

            try
            {
                pqPair = Utils.GetFastPQ(pq);
                pqCalcTime.Stop();
                calcTime = pqCalcTime.Elapsed;
                TLUtils.WriteLineAtBegin("Pq Fast calculation time: " + pqCalcTime.Elapsed);
                TLUtils.WriteLine("p: " + pqPair.Item1);
                TLUtils.WriteLine("q: " + pqPair.Item2);
            }
            catch (Exception e)
            {
                pqCalcTime = Stopwatch.StartNew();
                pqPair     = Utils.GetPQPollard(pq);
                pqCalcTime.Stop();
                calcTime = pqCalcTime.Elapsed;
                TLUtils.WriteLineAtBegin("Pq Pollard calculation time: " + pqCalcTime.Elapsed);
                TLUtils.WriteLine("p: " + pqPair.Item1);
                TLUtils.WriteLine("q: " + pqPair.Item2);
            }

            var p = TLString.FromUInt64(pqPair.Item1);
            var q = TLString.FromUInt64(pqPair.Item2);

            var innerData1 = new TLPQInnerDataDC
            {
                NewNonce    = newNonce,
                Nonce       = resPQ.Nonce,
                P           = p,
                Q           = q,
                PQ          = resPQ.PQ,
                ServerNonce = resPQ.ServerNonce,
                DCId        = dcId
            };

            return(innerData1);
        }
Esempio n. 2
0
        public void InitAsync(Action <WindowsPhone.Tuple <byte[], TLLong, TLLong> > callback, Action <TLRPCError> faultCallback = null)
        {
            var authTime = Stopwatch.StartNew();
            var newNonce = TLInt256.Random();

#if LOG_REGISTRATION
            TLUtils.WriteLog("Start ReqPQ");
#endif
            var nonce = TLInt128.Random();
            ReqPQAsync(nonce,
                       resPQ =>
            {
                GetServerPublicKeyAsync(_activeTransport.DCId, resPQ.ServerPublicKeyFingerprints,
                                        (index, publicKey) =>
                {
                    if (index < 0 || string.IsNullOrEmpty(publicKey))
                    {
                        var error = new TLRPCError {
                            Code = new TLInt(404), Message = new TLString("unknown public key")
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqPQ with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

                    var serverNonce = resPQ.ServerNonce;
                    if (!TLUtils.ByteArraysEqual(nonce.Value, resPQ.Nonce.Value))
                    {
                        var error = new TLRPCError {
                            Code = new TLInt(404), Message = new TLString("incorrect nonce")
                        };
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqPQ with error " + error);
#endif

                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    }

#if LOG_REGISTRATION
                    TLUtils.WriteLog("Stop ReqPQ");
#endif
                    TimeSpan calcTime;
                    WindowsPhone.Tuple <ulong, ulong> pqPair;
                    var innerData          = GetInnerData(new TLInt(TLUtils.GetProtocolDCId(_activeTransport.DCId, false, Constants.IsTestServer)), resPQ, newNonce, out calcTime, out pqPair);
                    var encryptedInnerData = GetEncryptedInnerData(innerData, publicKey);

#if LOG_REGISTRATION
                    var pq          = BitConverter.ToUInt64(resPQ.PQ.Data.Reverse().ToArray(), 0);
                    var logPQString = new StringBuilder();
                    logPQString.AppendLine("PQ Counters");
                    logPQString.AppendLine();
                    logPQString.AppendLine("pq: " + pq);
                    logPQString.AppendLine("p: " + pqPair.Item1);
                    logPQString.AppendLine("q: " + pqPair.Item2);
                    logPQString.AppendLine("encrypted_data length: " + encryptedInnerData.Data.Length);
                    TLUtils.WriteLog(logPQString.ToString());
                    TLUtils.WriteLog("Start ReqDHParams");
#endif
                    ReqDHParamsAsync(
                        resPQ.Nonce,
                        resPQ.ServerNonce,
                        innerData.P,
                        innerData.Q,
                        resPQ.ServerPublicKeyFingerprints[0],
                        encryptedInnerData,
                        serverDHParams =>
                    {
                        if (!TLUtils.ByteArraysEqual(nonce.Value, serverDHParams.Nonce.Value))
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("incorrect nonce")
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }
                        if (!TLUtils.ByteArraysEqual(serverNonce.Value, serverDHParams.ServerNonce.Value))
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("incorrect server_nonce")
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }

#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams");
#endif
                        var random = new SecureRandom();

                        var serverDHParamsOk = serverDHParams as TLServerDHParamsOk;
                        if (serverDHParamsOk == null)
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("Incorrect serverDHParams " + serverDHParams.GetType())
                            };
                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
#if LOG_REGISTRATION
                            TLUtils.WriteLog("ServerDHParams " + serverDHParams);
#endif
                            return;
                        }

                        var aesParams = GetAesKeyIV(resPQ.ServerNonce.ToBytes(), newNonce.ToBytes());

                        var decryptedAnswerWithHash = Utils.AesIge(serverDHParamsOk.EncryptedAnswer.Data, aesParams.Item1, aesParams.Item2, false);

                        var position          = 0;
                        var serverDHInnerData = (TLServerDHInnerData) new TLServerDHInnerData().FromBytes(decryptedAnswerWithHash.Skip(20).ToArray(), ref position);

                        var sha1 = Utils.ComputeSHA1(serverDHInnerData.ToBytes());
                        if (!TLUtils.ByteArraysEqual(sha1, decryptedAnswerWithHash.Take(20).ToArray()))
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("incorrect sha1 TLServerDHInnerData")
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }

                        if (!TLUtils.CheckPrime(serverDHInnerData.DHPrime.Data, serverDHInnerData.G.Value))
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("incorrect (p, q) pair")
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }

                        if (!TLUtils.CheckGaAndGb(serverDHInnerData.GA.Data, serverDHInnerData.DHPrime.Data))
                        {
                            var error = new TLRPCError {
                                Code = new TLInt(404), Message = new TLString("incorrect g_a")
                            };
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop ReqDHParams with error " + error);
#endif

                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        }

                        var bBytes = new byte[256];             //big endian B
                        random.NextBytes(bBytes);

                        var gbBytes = GetGB(bBytes, serverDHInnerData.G, serverDHInnerData.DHPrime);

                        var clientDHInnerData = new TLClientDHInnerData
                        {
                            Nonce       = resPQ.Nonce,
                            ServerNonce = resPQ.ServerNonce,
                            RetryId     = new TLLong(0),
                            GB          = TLString.FromBigEndianData(gbBytes)
                        };

                        var encryptedClientDHInnerData = GetEncryptedClientDHInnerData(clientDHInnerData, aesParams);
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Start SetClientDHParams");
#endif
                        SetClientDHParamsAsync(resPQ.Nonce, resPQ.ServerNonce, encryptedClientDHInnerData,
                                               dhGen =>
                        {
                            if (!TLUtils.ByteArraysEqual(nonce.Value, dhGen.Nonce.Value))
                            {
                                var error = new TLRPCError {
                                    Code = new TLInt(404), Message = new TLString("incorrect nonce")
                                };
#if LOG_REGISTRATION
                                TLUtils.WriteLog("Stop SetClientDHParams with error " + error);
#endif

                                if (faultCallback != null)
                                {
                                    faultCallback(error);
                                }
                                TLUtils.WriteLine(error.ToString());
                            }
                            if (!TLUtils.ByteArraysEqual(serverNonce.Value, dhGen.ServerNonce.Value))
                            {
                                var error = new TLRPCError {
                                    Code = new TLInt(404), Message = new TLString("incorrect server_nonce")
                                };
#if LOG_REGISTRATION
                                TLUtils.WriteLog("Stop SetClientDHParams with error " + error);
#endif

                                if (faultCallback != null)
                                {
                                    faultCallback(error);
                                }
                                TLUtils.WriteLine(error.ToString());
                            }

                            var dhGenOk = dhGen as TLDHGenOk;
                            if (dhGenOk == null)
                            {
                                var error = new TLRPCError {
                                    Code = new TLInt(404), Message = new TLString("Incorrect dhGen " + dhGen.GetType())
                                };
                                if (faultCallback != null)
                                {
                                    faultCallback(error);
                                }
                                TLUtils.WriteLine(error.ToString());
#if LOG_REGISTRATION
                                TLUtils.WriteLog("DHGen result " + serverDHParams);
#endif
                                return;
                            }


                            _authTimeElapsed = authTime.Elapsed;
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop SetClientDHParams");
#endif
                            var getKeyTimer = Stopwatch.StartNew();
                            var authKey     = GetAuthKey(bBytes, serverDHInnerData.GA.ToBytes(), serverDHInnerData.DHPrime.ToBytes());

                            var logCountersString = new StringBuilder();

                            logCountersString.AppendLine("Auth Counters");
                            logCountersString.AppendLine();
                            logCountersString.AppendLine("pq factorization time: " + calcTime);
                            logCountersString.AppendLine("calc auth key time: " + getKeyTimer.Elapsed);
                            logCountersString.AppendLine("auth time: " + _authTimeElapsed);
#if LOG_REGISTRATION
                            TLUtils.WriteLog(logCountersString.ToString());
#endif
                            //newNonce - little endian
                            //authResponse.ServerNonce - little endian
                            var salt      = GetSalt(newNonce.ToBytes(), resPQ.ServerNonce.ToBytes());
                            var sessionId = new byte[8];
                            random.NextBytes(sessionId);

                            TLUtils.WriteLine("Salt " + BitConverter.ToInt64(salt, 0) + " (" + BitConverter.ToString(salt) + ")");
                            TLUtils.WriteLine("Session id " + BitConverter.ToInt64(sessionId, 0) + " (" + BitConverter.ToString(sessionId) + ")");

                            callback(new WindowsPhone.Tuple <byte[], TLLong, TLLong>(authKey, new TLLong(BitConverter.ToInt64(salt, 0)), new TLLong(BitConverter.ToInt64(sessionId, 0))));
                        },
                                               error =>
                        {
#if LOG_REGISTRATION
                            TLUtils.WriteLog("Stop SetClientDHParams with error " + error.ToString());
#endif
                            if (faultCallback != null)
                            {
                                faultCallback(error);
                            }
                            TLUtils.WriteLine(error.ToString());
                        });
                    },
                        error =>
                    {
#if LOG_REGISTRATION
                        TLUtils.WriteLog("Stop ReqDHParams with error " + error.ToString());
#endif
                        if (faultCallback != null)
                        {
                            faultCallback(error);
                        }
                        TLUtils.WriteLine(error.ToString());
                    });
                });
            },
                       error =>
            {
#if LOG_REGISTRATION
                TLUtils.WriteLog("Stop ReqPQ with error " + error.ToString());
#endif
                if (faultCallback != null)
                {
                    faultCallback(error);
                }
                TLUtils.WriteLine(error.ToString());
            });
        }