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); }
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()); }); }