diff --git a/src/TgSharp.Core/Network/MtProtoSender.cs b/src/TgSharp.Core/Network/MtProtoSender.cs index 4a27da5a..5149ff14 100644 --- a/src/TgSharp.Core/Network/MtProtoSender.cs +++ b/src/TgSharp.Core/Network/MtProtoSender.cs @@ -24,6 +24,7 @@ public class MtProtoSender private readonly TcpTransport transport; private readonly Session session; + private readonly Random random; public readonly List needConfirmation = new List(); @@ -31,6 +32,7 @@ public MtProtoSender(TcpTransport transport, Session session) { this.transport = transport; this.session = session; + this.random = new Random(); } private int GenerateSequence(bool confirmed) @@ -74,7 +76,12 @@ private int GenerateSequence(bool confirmed) byte[] msgKey; byte[] ciphertext; - using (MemoryStream plaintextPacket = makeMemory(8 + 8 + 8 + 4 + 4 + packet.Length)) + + int size = 8 + 8 + 8 + 4 + 4 + packet.Length; + var randomPaddingLength = random.Next(1024 / 16) * 16 + 16 - size % 16; + size += randomPaddingLength; + + using (MemoryStream plaintextPacket = makeMemory(size)) { using (BinaryWriter plaintextWriter = new BinaryWriter(plaintextPacket)) { @@ -85,7 +92,11 @@ private int GenerateSequence(bool confirmed) plaintextWriter.Write(packet.Length); plaintextWriter.Write(packet); - msgKey = Helpers.CalcMsgKey(plaintextPacket.GetBuffer()); + var padding = new byte[randomPaddingLength]; + random.NextBytes(padding); + plaintextWriter.Write(padding); + + msgKey = Helpers.CalcMsgKey(session.AuthKey.Data, plaintextPacket.GetBuffer()); ciphertext = AES.EncryptAES(Helpers.CalcKey(session.AuthKey.Data, msgKey, true), plaintextPacket.GetBuffer()); } } diff --git a/src/TgSharp.Core/Utils/Helpers.cs b/src/TgSharp.Core/Utils/Helpers.cs index 96fb08fc..468bce61 100644 --- a/src/TgSharp.Core/Utils/Helpers.cs +++ b/src/TgSharp.Core/Utils/Helpers.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Security.Cryptography; using TgSharp.Core.MTProto.Crypto; @@ -27,69 +28,45 @@ public static byte[] GenerateRandomBytes(int num) return data; } - public static AESKeyData CalcKey(byte[] sharedKey, byte[] msgKey, bool client) + public static AESKeyData CalcKey(byte[] authKey, byte[] msgKey, bool client) { int x = client ? 0 : 8; - byte[] buffer = new byte[48]; - Array.Copy(msgKey, 0, buffer, 0, 16); // buffer[0:16] = msgKey - Array.Copy(sharedKey, x, buffer, 16, 32); // buffer[16:48] = authKey[x:x+32] - byte[] sha1a = sha1(buffer); // sha1a = sha1(buffer) + //sha256_a = SHA256 (msg_key + substr (auth_key, x, 36)); + var sha256A = SHA256(msgKey.Concat(authKey.Skip(x).Take(36)).ToArray()); + //sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key); + var sha256B = SHA256(authKey.Skip(40 + x).Take(36).Concat(msgKey).ToArray()); + //aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8); + var key = sha256A.Take(8).Concat(sha256B.Skip(8).Take(16)).Concat(sha256A.Skip(24).Take(8)).ToArray(); + //aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8); + var iv = sha256B.Take(8).Concat(sha256A.Skip(8).Take(16)).Concat(sha256B.Skip(24).Take(8)).ToArray(); - Array.Copy(sharedKey, 32 + x, buffer, 0, 16); // buffer[0:16] = authKey[x+32:x+48] - Array.Copy(msgKey, 0, buffer, 16, 16); // buffer[16:32] = msgKey - Array.Copy(sharedKey, 48 + x, buffer, 32, 16); // buffer[32:48] = authKey[x+48:x+64] - byte[] sha1b = sha1(buffer); // sha1b = sha1(buffer) - - Array.Copy(sharedKey, 64 + x, buffer, 0, 32); // buffer[0:32] = authKey[x+64:x+96] - Array.Copy(msgKey, 0, buffer, 32, 16); // buffer[32:48] = msgKey - byte[] sha1c = sha1(buffer); // sha1c = sha1(buffer) - - Array.Copy(msgKey, 0, buffer, 0, 16); // buffer[0:16] = msgKey - Array.Copy(sharedKey, 96 + x, buffer, 16, 32); // buffer[16:48] = authKey[x+96:x+128] - byte[] sha1d = sha1(buffer); // sha1d = sha1(buffer) - - byte[] key = new byte[32]; // key = sha1a[0:8] + sha1b[8:20] + sha1c[4:16] - Array.Copy(sha1a, 0, key, 0, 8); - Array.Copy(sha1b, 8, key, 8, 12); - Array.Copy(sha1c, 4, key, 20, 12); - - byte[] iv = new byte[32]; // iv = sha1a[8:20] + sha1b[0:8] + sha1c[16:20] + sha1d[0:8] - Array.Copy(sha1a, 8, iv, 0, 12); - Array.Copy(sha1b, 0, iv, 12, 8); - Array.Copy(sha1c, 16, iv, 20, 4); - Array.Copy(sha1d, 0, iv, 24, 8); return new AESKeyData(key, iv); } - public static byte[] CalcMsgKey(byte[] data) + public static byte[] CalcMsgKey(byte[] authKey, byte[] data) { - byte[] msgKey = new byte[16]; - Array.Copy(sha1(data), 4, msgKey, 0, 16); - return msgKey; - } + //msg_key_large = SHA256 (substr (auth_key, 88+0, 32) + plaintext + random_padding); + var msgKeyLarge = SHA256(authKey.Skip(88).Take(32).Concat(data).ToArray()); - public static byte[] CalcMsgKey(byte[] data, int offset, int limit) - { - byte[] msgKey = new byte[16]; - Array.Copy(sha1(data, offset, limit), 4, msgKey, 0, 16); - return msgKey; + //msg_key = substr (msg_key_large, 8, 16); + return msgKeyLarge.Skip(8).Take(16).ToArray(); } - public static byte[] sha1(byte[] data) + public static byte[] SHA256(byte[] data) { - using (SHA1 sha1 = new SHA1Managed()) + using (SHA256 sha256 = new SHA256Managed()) { - return sha1.ComputeHash(data); + return sha256.ComputeHash(data); } } - public static byte[] sha1(byte[] data, int offset, int limit) + public static byte[] SHA256(byte[] data, int offset, int limit) { - using (SHA1 sha1 = new SHA1Managed()) + using (SHA256 sha256 = new SHA256Managed()) { - return sha1.ComputeHash(data, offset, limit); + return sha256.ComputeHash(data, offset, limit); } } }