// return big-endian authKey public static byte[] GetAuthKey(byte[] bBytes, byte[] g_aData, byte[] dhPrimeData) { int position = 0; var b = new BigInteger(bBytes.Reverse().Concat(new byte[] { 0x00 }).ToArray()); var dhPrime = TLObject.GetObject <TLString>(dhPrimeData, ref position).ToBigInteger(); position = 0; var g_a = TLObject.GetObject <TLString>(g_aData, ref position).ToBigInteger(); var authKey = BigInteger.ModPow(g_a, b, dhPrime).ToByteArray(); // little endian + (may be) zero last byte //remove last zero byte if (authKey[authKey.Length - 1] == 0x00) { authKey = authKey.SubArray(0, authKey.Length - 1); } authKey = authKey.Reverse().ToArray(); if (authKey.Length > 256) { #if DEBUG var authKeyInfo = new StringBuilder(); authKeyInfo.AppendLine("auth_key length > 256: " + authKey.Length); authKeyInfo.AppendLine("g_a=" + g_a); authKeyInfo.AppendLine("b=" + b); authKeyInfo.AppendLine("dhPrime=" + dhPrime); Execute.ShowDebugMessage(authKeyInfo.ToString()); #endif var correctedAuth = new byte[256]; Array.Copy(authKey, authKey.Length - 256, correctedAuth, 0, 256); authKey = correctedAuth; } else if (authKey.Length < 256) { #if DEBUG var authKeyInfo = new StringBuilder(); authKeyInfo.AppendLine("auth_key length < 256: " + authKey.Length); authKeyInfo.AppendLine("g_a=" + g_a); authKeyInfo.AppendLine("b=" + b); authKeyInfo.AppendLine("dhPrime=" + dhPrime); Execute.ShowDebugMessage(authKeyInfo.ToString()); #endif var correctedAuth = new byte[256]; Array.Copy(authKey, 0, correctedAuth, 256 - authKey.Length, authKey.Length); for (var i = 0; i < 256 - authKey.Length; i++) { authKey[i] = 0; } authKey = correctedAuth; } return(authKey); }
private void SetMinMessageId(byte[] bytes) { try { var position = 0; var encryptedMessage = (TLEncryptedTransportMessage) new TLEncryptedTransportMessage().FromBytes(bytes, ref position); encryptedMessage.Decrypt(AuthKey); position = 0; TLTransportMessage transportMessage; transportMessage = TLObject.GetObject <TLTransportMessage>(encryptedMessage.Data, ref position); MinMessageId = transportMessage.MessageId.Value; System.Diagnostics.Debug.WriteLine("TCPTransport set min message_id={0} seq_no={1}", transportMessage.MessageId, transportMessage.SeqNo); } catch (Exception ex) { Execute.ShowDebugMessage("SetMessageId exception " + ex); } }
private static TLConfigSimple DecryptSimpleConfig(string dataString) { TLConfigSimple result = null; #if !WIN_RT var base64Chars = dataString.Where(ch => { var isGoodBase64 = (ch == '+') || (ch == '=') || (ch == '/') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'); return(isGoodBase64); }).ToArray(); var cleanDataString = new string(base64Chars); const int kGoodSizeBase64 = 344; if (cleanDataString.Length != kGoodSizeBase64) { Log(string.Format("Bad base64 size {0} required {1}", cleanDataString.Length, kGoodSizeBase64)); return(null); } byte[] data = null; try { data = Convert.FromBase64String(cleanDataString); } catch (Exception ex) { Log("Bad base64 bytes"); return(null); } const int kGoodSizeData = 256; if (data.Length != kGoodSizeData) { Log(string.Format("Bad data size {0} required {1}", data.Length, kGoodSizeData)); return(null); } var xml = "<RSAKeyValue><Modulus>yr+18Rex2ohtVy8sroGPBwXD3DOoKCSpjDqYoXgCqB7ioln4eDCFfOBUlfXUEvM/fnKCpF46VkAftlb4VuPDeQSS/ZxZYEGqHaywlroVnXHIjgqoxiAd192xRGreuXIaUKmkwlM9JID9WS2jUsTpzQ91L8MEPLJ/4zrBwZua8W5fECwCCh2c9G5IzzBm+otMS/YKwmR1olzRCyEkyAEjXWqBI9Ftv5eG8m0VkBzOG655WIYdyV0HfDK/NWcvGqa0w/nriMD6mDjKOryamw0OP9QuYgMN0C9xMW9y8SmP4h92OAWodTYgY1hZCxdv6cs5UnW9+PWvS+WIbkh+GaWYxw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"; var provider = new RSACryptoServiceProvider(); provider.FromXmlString(xml); var parameters = provider.ExportParameters(false); var modulus = parameters.Modulus; var exponent = parameters.Exponent; var dataBI = new BigInteger(data.Reverse().Concat(new byte[] { 0x00 }).ToArray()); var exponentBI = new BigInteger(exponent.Reverse().Concat(new byte[] { 0x00 }).ToArray()); var modulusBI = new BigInteger(modulus.Reverse().Concat(new byte[] { 0x00 }).ToArray()); var authKey = BigInteger.ModPow(dataBI, exponentBI, modulusBI).ToByteArray(); if (authKey[authKey.Length - 1] == 0x00) { authKey = authKey.SubArray(0, authKey.Length - 1); } authKey = authKey.Reverse().ToArray(); if (authKey.Length > 256) { var correctedAuth = new byte[256]; Array.Copy(authKey, authKey.Length - 256, correctedAuth, 0, 256); authKey = correctedAuth; } else if (authKey.Length < 256) { var correctedAuth = new byte[256]; Array.Copy(authKey, 0, correctedAuth, 256 - authKey.Length, authKey.Length); for (var i = 0; i < 256 - authKey.Length; i++) { authKey[i] = 0; } authKey = correctedAuth; } var key = authKey.SubArray(0, 32); var iv = authKey.SubArray(16, 16); var encryptedData = authKey.SubArray(32, authKey.Length - 32); var cipher = CipherUtilities.GetCipher("AES/CBC/NOPADDING"); var param = new KeyParameter(key); cipher.Init(false, new ParametersWithIV(param, iv)); var decryptedData = cipher.DoFinal(encryptedData); const int kDigestSize = 16; var hash = Utils.ComputeSHA256(decryptedData.SubArray(0, 208)); for (var i = 0; i < kDigestSize; i++) { if (hash[i] != decryptedData[208 + i]) { Log("Bad digest"); return(null); } } var position = 4; var length = BitConverter.ToInt32(decryptedData, 0); if (length <= 0 || length > 208 || length % 4 != 0) { Log(string.Format("Bad length {0}", length)); return(null); } try { result = TLObject.GetObject <TLConfigSimple>(decryptedData, ref position); } catch (Exception ex) { Log("Could not read configSimple"); return(null); } if (position != length) { Log(string.Format("Bad read length {0} shoud be {1}", position, length)); return(null); } #endif return(result); }