diff --git a/Apps/ClientConsoleApp/Program.cs b/Apps/ClientConsoleApp/Program.cs index 25b5163..4098c2a 100644 --- a/Apps/ClientConsoleApp/Program.cs +++ b/Apps/ClientConsoleApp/Program.cs @@ -5,12 +5,14 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; +using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using TeleSharp.TL; using TLSharp.Core; using TLSharp.Core.MTProto.Crypto; +using static TLSharp.Core.MTProto.Serializers; namespace ClientConsoleApp { @@ -20,7 +22,7 @@ namespace ClientConsoleApp static void Main(string[] args) { - TestNewNonce(); + //TestRSA(); Thread.Sleep(2000); Console.WriteLine("Hello World!"); @@ -137,5 +139,43 @@ namespace ClientConsoleApp return; } + + private static void TestRSA() + { + BigInteger e, n, d; + using (var rsa = new RSACryptoServiceProvider(2048)) + { + try + { + var keys = rsa.ExportParameters(true); + + var strE = BitConverter.ToString(keys.Exponent).Replace("-", ""); + var strN = BitConverter.ToString(keys.Modulus).Replace("-", ""); + var strD = BitConverter.ToString(keys.D).Replace("-", ""); + + e = new BigInteger(strE, 16); + n = new BigInteger(strN, 16); + d = new BigInteger(strD, 16); + + //e = new BigInteger(1, keys.Exponent); + //n = new BigInteger(1, keys.Modulus); + //d = new BigInteger(1, keys.D); + } + finally + { + rsa.PersistKeyInCsp = false; + } + } + + var text1 = "abcd--------------------------------123456789--------------------------------------------------------------------------------mnabcd--------------------------------123456789-----------------------------------------------------------------------------mn"; + var data = Encoding.ASCII.GetBytes(text1); + + byte[] ciphertext = new BigInteger(1, data).ModPow(e, n).ToByteArrayUnsigned(); + byte[] cleartext = new BigInteger(1, ciphertext).ModPow(d, n).ToByteArrayUnsigned(); + + var text2 = ASCIIEncoding.ASCII.GetString(cleartext); + + return; + } } } diff --git a/Apps/TlgListenerApplication/Program.cs b/Apps/TlgListenerApplication/Program.cs index 569db3f..76b0653 100644 --- a/Apps/TlgListenerApplication/Program.cs +++ b/Apps/TlgListenerApplication/Program.cs @@ -79,6 +79,9 @@ namespace TlgListenerApplication BigInteger gb = null; var sequenceNumber = 1; ulong? messageId = null; + var privateKey = new BigInteger("582A4D5EE3A45C1AEEBDECD549D1FD4E12337B05C4C0A03FA8FF4A0A7B2861BAB86E8B58A70AAB9CF173FA313348239E28B17D34C7CEC8B68544BAD8623A306D747B7DC1D3D064FA73CE96893E8AFC36F7CDF58A383F48BDEC284D30BFFBC3F1A413DC869B3692EDD26004EE661C021BDA32F124D6631C67891E3E35EEDEAA08BFED8DBB7A6CC1D550CF16C67703BBDFFF0500FD81A55F98D92ECD67CE3CC31B766EA0DFBA284E18677E46036D9ED04105AAD11E97FD675F49A3B54D5AD395AA3C5B8343CDFF70C2E2A9243A47FBC5F541BBAE910B5DD1BF574B1E732A105C2B8F5239A4DFA0BCE0559F18BA0C44D31A279FA7CDCA612BD8F9796EBD114F7FA9", 16); + AuthKey authKey = null; + //var getingCounter = 0; //while (true) //{ @@ -97,7 +100,7 @@ namespace TlgListenerApplication uint responseCode = 0; int innerCode = 0; - long authkey = 123456789; + long authkeysample = 123456789; const long step1Constructor = 0x60469778; const long step2Constructor = 0xd712e4be; @@ -132,11 +135,19 @@ namespace TlgListenerApplication servernonce = binaryReader2.ReadBytes(16); var p = binaryReader2.ReadBytes(4); var q = binaryReader2.ReadBytes(8); - var targetFingerprint = binaryReader2.ReadBytes(8); + var targetFingerprint = BitConverter.ToString(binaryReader2.ReadBytes(8)).Replace("-", string.Empty); //TODO: need to decryption var ciphertext = Bytes.read(binaryReader2); - Array.Copy(ciphertext, ciphertext.Length - 32, newNonce, 0, 32); + ciphertext = RSA.Decrypt(targetFingerprint, ciphertext, privateKey, 0, ciphertext.Length); + var cipherReader = new BinaryReader(new MemoryStream(ciphertext, false)); + var hashsum = cipherReader.ReadBytes(20); + var innercode = cipherReader.ReadUInt32();//0x83c95aec + var pq = cipherReader.ReadBytes(20); + var noncetemp = cipherReader.ReadBytes(16); + var servernoncetemp = cipherReader.ReadBytes(16); + newNonce = cipherReader.ReadBytes(32); + //Array.Copy(ciphertext, ciphertext.Length - 32, newNonce, 0, 32); //ciphertext.CopyTo(newnoncetemp, ciphertext.Length - 32); } else if (responseCode == step3Constructor) //---Step1_PQRequest @@ -146,7 +157,9 @@ namespace TlgListenerApplication //TODO: need to decryption var ciphertext = Bytes.read(binaryReader2); - var binaryReadernner = new BinaryReader(new MemoryStream(ciphertext, false)); + AESKeyData key = AES.GenerateKeyDataFromNonces(servernonce, newNonce); + var cleartext = AES.DecryptAES(key, ciphertext); + var binaryReadernner = new BinaryReader(new MemoryStream(cleartext, false)); var hasheddata = binaryReadernner.ReadBytes(20); var client_dh_inner_data_code = binaryReadernner.ReadUInt32(); if (client_dh_inner_data_code != 0x6643b654) @@ -161,7 +174,9 @@ namespace TlgListenerApplication } else { - var decodeMessage = DecodeMessage(tcpMessage.Body, null); + var _gba = gb.ModPow(a, dhPrime); + authKey = new AuthKey(_gba); + var decodeMessage = DecodeMessage(tcpMessage.Body, authKey); var objrawReader = new BinaryReader(new MemoryStream(decodeMessage.Item1, false)); messageId = decodeMessage.Item2; innerCode = objrawReader.ReadInt32(); @@ -182,11 +197,11 @@ namespace TlgListenerApplication var invokewithlayer = (TLRequestInvokeWithLayer)obj; if (invokewithlayer.Query is TLRequestInitConnection) { - + var requestInitConnection = (TLRequestInitConnection)invokewithlayer.Query; } else if (invokewithlayer.Query is TLRequestSendCode) { - + var requestSendCode = (TLRequestSendCode)invokewithlayer.Query; } } else if (obj is TLRequestSendCode) @@ -266,7 +281,7 @@ namespace TlgListenerApplication else if (responseCode == step3Constructor) { var _gba = gb.ModPow(a, dhPrime); - AuthKey authKey = new AuthKey(_gba); + authKey = new AuthKey(_gba); var newNonceHash = authKey.CalcNewNonceHash(newNonce, 1); const uint innerCodeTemp = 0x3bcbf734; using (var memoryStream = new MemoryStream()) @@ -415,7 +430,7 @@ namespace TlgListenerApplication if (innerCode != 0) { - outputdata = PrepareToSend2(outputdata, authkey, servernonce, sequenceNumber); + outputdata = PrepareToSend2(outputdata, authKey.Id, 0, 0, 0, servernonce, sequenceNumber, authKey); } else outputdata = PrepareToSend(outputdata); @@ -548,22 +563,37 @@ namespace TlgListenerApplication } } - public static byte[] PrepareToSend2(byte[] message, long authkey, byte[] servernonce, int sequenceNumber) + public static byte[] PrepareToSend2(byte[] message, ulong authKeyId, ulong salt, ulong sessionId, ulong messageId, byte[] servernonce, int sequenceNumber, AuthKey authKey) { using (var memoryStream = new MemoryStream()) { using (var binaryWriter = new BinaryWriter(memoryStream)) { - binaryWriter.Write(authkey); - binaryWriter.Write(servernonce); - binaryWriter.Write(authkey);//salt - binaryWriter.Write(authkey);//sessionId - binaryWriter.Write(authkey);//messageid + //binaryWriter.Write(servernonce); + binaryWriter.Write(salt);//salt + binaryWriter.Write(sessionId);//sessionId + binaryWriter.Write(messageId);//messageid binaryWriter.Write(sequenceNumber); binaryWriter.Write(message.Length); binaryWriter.Write(message); + message = memoryStream.ToArray(); + } + } + + byte[] msgKey = Helpers.CalcMsgKey(message); + AESKeyData key = Helpers.CalcKey(authKey.Data, msgKey, false); + message = AES.EncryptAES(key, message); + + using (var memoryStream = new MemoryStream()) + { + using (var binaryWriter = new BinaryWriter(memoryStream)) + { + binaryWriter.Write(authKeyId); + binaryWriter.Write(msgKey); + binaryWriter.Write(message); + return memoryStream.ToArray(); } } @@ -587,7 +617,7 @@ namespace TlgListenerApplication } #region helpers - private static Tuple DecodeMessage(byte[] body, AESKeyData keyData) + private static Tuple DecodeMessage(byte[] body, AuthKey authkey) { byte[] message; ulong remoteMessageId; @@ -601,10 +631,11 @@ namespace TlgListenerApplication ulong remoteAuthKeyId = inputReader.ReadUInt64(); // TODO: check auth key id byte[] msgKey = inputReader.ReadBytes(16); // TODO: check msg_key correctness - + AESKeyData keyData = Helpers.CalcKey(authkey.Data, msgKey, true); //TODO: return to decryption - //byte[] plaintext = AES.DecryptAES(keyData, inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position))); - byte[] plaintext = inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)); + var cipherText = inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)); + byte[] plaintext = AES.DecryptAES(keyData, cipherText); + //byte[] plaintext = inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)); using (MemoryStream plaintextStream = new MemoryStream(plaintext)) using (BinaryReader plaintextReader = new BinaryReader(plaintextStream)) diff --git a/TLSharp.Core/Auth/Step2_DHExchange.cs b/TLSharp.Core/Auth/Step2_DHExchange.cs index ca3a190..8e04941 100644 --- a/TLSharp.Core/Auth/Step2_DHExchange.cs +++ b/TLSharp.Core/Auth/Step2_DHExchange.cs @@ -63,28 +63,27 @@ namespace TLSharp.Core.Auth pqInnerDataWriter.Write(newNonce); //TODO--change by main version code---- - byte[] ciphertext = pqInnerData.ToArray(); - byte[] targetFingerprint = fingerprints[0]; + //byte[] ciphertext = pqInnerData.ToArray(); + //byte[] targetFingerprint = fingerprints[0]; + byte[] ciphertext = null; + byte[] targetFingerprint = null; + foreach (byte[] fingerprint in fingerprints) + { + ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty), + pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position); + if (ciphertext != null) + { + targetFingerprint = fingerprint; + break; + } + } - //byte[] ciphertext = null; - //byte[] targetFingerprint = null; - //foreach (byte[] fingerprint in fingerprints) - //{ - // ciphertext = RSA.Encrypt(BitConverter.ToString(fingerprint).Replace("-", string.Empty), - // pqInnerData.GetBuffer(), 0, (int)pqInnerData.Position); - // if (ciphertext != null) - // { - // targetFingerprint = fingerprint; - // break; - // } - //} - - //if (ciphertext == null) - //{ - // throw new InvalidOperationException( - // String.Format("not found valid key for fingerprints: {0}", String.Join(", ", fingerprints))); - //} + if (ciphertext == null) + { + throw new InvalidOperationException( + String.Format("not found valid key for fingerprints: {0}", String.Join(", ", fingerprints))); + } using (MemoryStream reqDHParams = new MemoryStream(1024)) { diff --git a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs index 9c22bef..a3e2a81 100644 --- a/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs +++ b/TLSharp.Core/Auth/Step3_CompleteDHExchange.cs @@ -108,7 +108,8 @@ namespace TLSharp.Core.Auth // encryption //TODO: uncomment encryption - byte[] clientDhInnerDataEncryptedBytes = clientDHInnerDataBytes;// AES.EncryptAES(key, clientDHInnerDataBytes); + //byte[] clientDhInnerDataEncryptedBytes = clientDHInnerDataBytes; + byte[] clientDhInnerDataEncryptedBytes = AES.EncryptAES(key, clientDHInnerDataBytes); // logger.debug("inner data encrypted {0}: {1}", clientDhInnerDataEncryptedBytes.Length, BitConverter.ToString(clientDhInnerDataEncryptedBytes).Replace("-", "")); diff --git a/TLSharp.Core/MTProto/Crypto/RSA.cs b/TLSharp.Core/MTProto/Crypto/RSA.cs index 55cbcb0..a557b1a 100644 --- a/TLSharp.Core/MTProto/Crypto/RSA.cs +++ b/TLSharp.Core/MTProto/Crypto/RSA.cs @@ -46,7 +46,8 @@ namespace TLSharp.Core.MTProto.Crypto { return ciphertext; } - else { + else + { byte[] paddedCiphertext = new byte[256]; int padding = 256 - ciphertext.Length; for (int i = 0; i < padding; i++) @@ -59,11 +60,18 @@ namespace TLSharp.Core.MTProto.Crypto } } + + public byte[] Decrypt(byte[] cipherdata, BigInteger d, int offset, int length) + { + byte[] text = new BigInteger(1, cipherdata).ModPow(d, m).ToByteArrayUnsigned(); + return text; + } } public class RSA { private static readonly Dictionary serverKeys = new Dictionary() { - { "216be86c022bb4c3", new RSAServerKey("216be86c022bb4c3", new BigInteger("00C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F91F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD15A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F", 16), new BigInteger("010001", 16)) } + { "216be86c022bb4c3_", new RSAServerKey("216be86c022bb4c3_", new BigInteger("00C150023E2F70DB7985DED064759CFECF0AF328E69A41DAF4D6F01B538135A6F91F8F8B2A0EC9BA9720CE352EFCF6C5680FFC424BD634864902DE0B4BD6D49F4E580230E3AE97D95C8B19442B3C0A10D8F5633FECEDD6926A7F6DAB0DDB7D457F9EA81B8465FCD6FFFEED114011DF91C059CAEDAF97625F6C96ECC74725556934EF781D866B34F011FCE4D835A090196E9A5F0E4449AF7EB697DDB9076494CA5F81104A305B6DD27665722C46B60E5DF680FB16B210607EF217652E60236C255F6A28315F4083A96791D7214BF64C1DF4FD0DB1944FB26A2A57031B32EEE64AD15A8BA68885CDE74A5BFC920F6ABF59BA5C75506373E7130F9042DA922179251F", 16), new BigInteger("010001", 16)) }, + { "216be86c022bb4c3", new RSAServerKey("216be86c022bb4c3", new BigInteger("E5F6E2F9781DD46D169B6F072382A1443D10F22D31CE5F007B3B2FAE37BD9EAB3B69A76E9CA75D8C596CCA70A9252D67562199E460F3644A3BFBAE61405B7AF92ED0F8BD1E09D4765BFE64C8CF1391E6A69D3EB3E8B42538A33EAC86613EE76B3EF5F5CBB58DAA17E53E346F5F5EB20E2F8C5F5D0EEF9FED78E0399689C1B209B34730CBFE022E2BC2FD6A2B5A76FD8D5B3BCB1AC10F9D88CA6DEBB4E45F91460EC3C46D3B03AAB8438C8F294AAE852A7C9A77997BEE02773788CB66619F8994A4E4541FC6E652BE7349A2D7DEBD2A8D6FC6A90371D544682EA1CEB9FBFE4B31AC17753945A3B598A22B927FFF7ED00600772F5041A86A2DD20D4623EA9A0D6D", 16), new BigInteger("010001", 16)) } }; public static byte[] Encrypt(string fingerprint, byte[] data, int offset, int length) @@ -78,6 +86,19 @@ namespace TLSharp.Core.MTProto.Crypto return key.Encrypt(data, offset, length); } + + public static byte[] Decrypt(string fingerprint, byte[] cipherdata, BigInteger d, int offset, int length) + { + string fingerprintLower = fingerprint.ToLower(); + if (!serverKeys.ContainsKey(fingerprintLower)) + { + return null; + } + + RSAServerKey key = serverKeys[fingerprintLower]; + + return key.Decrypt(cipherdata, d, offset, length); + } } } diff --git a/TLSharp.Core/Network/MtProtoSender.cs b/TLSharp.Core/Network/MtProtoSender.cs index 7eb0c43..6674907 100644 --- a/TLSharp.Core/Network/MtProtoSender.cs +++ b/TLSharp.Core/Network/MtProtoSender.cs @@ -85,8 +85,8 @@ namespace TLSharp.Core.Network msgKey = Helpers.CalcMsgKey(plaintextPacket.GetBuffer()); //TODO: return to encryption - //ciphertext = AES.EncryptAES(Helpers.CalcKey(_session.AuthKey.Data, msgKey, true), plaintextPacket.GetBuffer()); - ciphertext = plaintextPacket.GetBuffer(); + ciphertext = AES.EncryptAES(Helpers.CalcKey(_session.AuthKey.Data, msgKey, true), plaintextPacket.GetBuffer()); + //ciphertext = plaintextPacket.GetBuffer(); } } @@ -120,8 +120,8 @@ namespace TLSharp.Core.Network AESKeyData keyData = Helpers.CalcKey(_session.AuthKey.Data, msgKey, false); //TODO: back to encryption - //byte[] plaintext = AES.DecryptAES(keyData, inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position))); - byte[] plaintext = inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)); + byte[] plaintext = AES.DecryptAES(keyData, inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position))); + //byte[] plaintext = inputReader.ReadBytes((int)(inputStream.Length - inputStream.Position)); using (MemoryStream plaintextStream = new MemoryStream(plaintext)) using (BinaryReader plaintextReader = new BinaryReader(plaintextStream))