Exemplo n.º 1
0
        private static TLString GetEncryptedClientDHInnerData(TLClientDHInnerData clientDHInnerData, WindowsPhone.Tuple <byte[], byte[]> aesParams)
        {
            var random = new Random();
            var client_DH_inner_data = clientDHInnerData.ToBytes();

            var client_DH_inner_dataWithHash = TLUtils.Combine(Utils.ComputeSHA1(client_DH_inner_data), client_DH_inner_data);
            var addedBytesLength             = 16 - (client_DH_inner_dataWithHash.Length % 16);

            if (addedBytesLength > 0 && addedBytesLength < 16)
            {
                var addedBytes = new byte[addedBytesLength];
                random.NextBytes(addedBytes);
                client_DH_inner_dataWithHash = TLUtils.Combine(client_DH_inner_dataWithHash, addedBytes);
                //TLUtils.WriteLine(string.Format("Added {0} bytes", addedBytesLength));
            }

            var aesEncryptClientDHInnerDataWithHash = Utils.AesIge(client_DH_inner_dataWithHash, aesParams.Item1, aesParams.Item2, true);

            return(TLString.FromBigEndianData(aesEncryptClientDHInnerDataWithHash));
        }
Exemplo n.º 2
0
        private static byte[] GetEncryptedClientDHInnerData(TLClientDHInnerData clientDHInnerData, Tuple <byte[], byte[]> aesParams)
        {
            var random = new Random();
            var client_DH_inner_data = clientDHInnerData.ToArray();

            var client_DH_inner_dataWithHash = Utils.ComputeSHA1(client_DH_inner_data).Concat(client_DH_inner_data).ToArray();
            var addedBytesLength             = 16 - (client_DH_inner_dataWithHash.Length % 16);

            if (addedBytesLength > 0 && addedBytesLength < 16)
            {
                var addedBytes = new byte[addedBytesLength];
                random.NextBytes(addedBytes);
                client_DH_inner_dataWithHash = client_DH_inner_dataWithHash.Concat(addedBytes).ToArray();
                //TLUtils.WriteLine(string.Format("Added {0} bytes", addedBytesLength));
            }

            var aesEncryptClientDHInnerDataWithHash = Utils.AesIge(client_DH_inner_dataWithHash, aesParams.Item1, aesParams.Item2, true);

            return(aesEncryptClientDHInnerDataWithHash);
        }
Exemplo n.º 3
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());
            });
        }