Skip to content

Commit cb698cc

Browse files
committed
MTProto 2.0 Initial Commit
1 parent a1aabb6 commit cb698cc

2 files changed

Lines changed: 34 additions & 46 deletions

File tree

src/TgSharp.Core/Network/MtProtoSender.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,15 @@ public class MtProtoSender
2424

2525
private readonly TcpTransport transport;
2626
private readonly Session session;
27+
private readonly Random random;
2728

2829
public readonly List<ulong> needConfirmation = new List<ulong>();
2930

3031
public MtProtoSender(TcpTransport transport, Session session)
3132
{
3233
this.transport = transport;
3334
this.session = session;
35+
this.random = new Random();
3436
}
3537

3638
private int GenerateSequence(bool confirmed)
@@ -74,7 +76,12 @@ private int GenerateSequence(bool confirmed)
7476

7577
byte[] msgKey;
7678
byte[] ciphertext;
77-
using (MemoryStream plaintextPacket = makeMemory(8 + 8 + 8 + 4 + 4 + packet.Length))
79+
80+
int size = 8 + 8 + 8 + 4 + 4 + packet.Length;
81+
var randomPaddingLength = random.Next(1024 / 16) * 16 + 16 - size % 16;
82+
size += randomPaddingLength;
83+
84+
using (MemoryStream plaintextPacket = makeMemory(size))
7885
{
7986
using (BinaryWriter plaintextWriter = new BinaryWriter(plaintextPacket))
8087
{
@@ -85,7 +92,11 @@ private int GenerateSequence(bool confirmed)
8592
plaintextWriter.Write(packet.Length);
8693
plaintextWriter.Write(packet);
8794

88-
msgKey = Helpers.CalcMsgKey(plaintextPacket.GetBuffer());
95+
var padding = new byte[randomPaddingLength];
96+
random.NextBytes(padding);
97+
plaintextWriter.Write(padding);
98+
99+
msgKey = Helpers.CalcMsgKey(session.AuthKey.Data, plaintextPacket.GetBuffer());
89100
ciphertext = AES.EncryptAES(Helpers.CalcKey(session.AuthKey.Data, msgKey, true), plaintextPacket.GetBuffer());
90101
}
91102
}

src/TgSharp.Core/Utils/Helpers.cs

Lines changed: 21 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Linq;
23
using System.Security.Cryptography;
34
using TgSharp.Core.MTProto.Crypto;
45

@@ -27,69 +28,45 @@ public static byte[] GenerateRandomBytes(int num)
2728
return data;
2829
}
2930

30-
public static AESKeyData CalcKey(byte[] sharedKey, byte[] msgKey, bool client)
31+
public static AESKeyData CalcKey(byte[] authKey, byte[] msgKey, bool client)
3132
{
3233
int x = client ? 0 : 8;
33-
byte[] buffer = new byte[48];
3434

35-
Array.Copy(msgKey, 0, buffer, 0, 16); // buffer[0:16] = msgKey
36-
Array.Copy(sharedKey, x, buffer, 16, 32); // buffer[16:48] = authKey[x:x+32]
37-
byte[] sha1a = sha1(buffer); // sha1a = sha1(buffer)
35+
//sha256_a = SHA256 (msg_key + substr (auth_key, x, 36));
36+
var sha256A = SHA256(msgKey.Concat(authKey.Skip(x).Take(36)).ToArray());
37+
//sha256_b = SHA256 (substr (auth_key, 40+x, 36) + msg_key);
38+
var sha256B = SHA256(authKey.Skip(40 + x).Take(36).Concat(msgKey).ToArray());
39+
//aes_key = substr (sha256_a, 0, 8) + substr (sha256_b, 8, 16) + substr (sha256_a, 24, 8);
40+
var key = sha256A.Take(8).Concat(sha256B.Skip(8).Take(16)).Concat(sha256A.Skip(24).Take(8)).ToArray();
41+
//aes_iv = substr (sha256_b, 0, 8) + substr (sha256_a, 8, 16) + substr (sha256_b, 24, 8);
42+
var iv = sha256B.Take(8).Concat(sha256A.Skip(8).Take(16)).Concat(sha256B.Skip(24).Take(8)).ToArray();
3843

39-
Array.Copy(sharedKey, 32 + x, buffer, 0, 16); // buffer[0:16] = authKey[x+32:x+48]
40-
Array.Copy(msgKey, 0, buffer, 16, 16); // buffer[16:32] = msgKey
41-
Array.Copy(sharedKey, 48 + x, buffer, 32, 16); // buffer[32:48] = authKey[x+48:x+64]
42-
byte[] sha1b = sha1(buffer); // sha1b = sha1(buffer)
43-
44-
Array.Copy(sharedKey, 64 + x, buffer, 0, 32); // buffer[0:32] = authKey[x+64:x+96]
45-
Array.Copy(msgKey, 0, buffer, 32, 16); // buffer[32:48] = msgKey
46-
byte[] sha1c = sha1(buffer); // sha1c = sha1(buffer)
47-
48-
Array.Copy(msgKey, 0, buffer, 0, 16); // buffer[0:16] = msgKey
49-
Array.Copy(sharedKey, 96 + x, buffer, 16, 32); // buffer[16:48] = authKey[x+96:x+128]
50-
byte[] sha1d = sha1(buffer); // sha1d = sha1(buffer)
51-
52-
byte[] key = new byte[32]; // key = sha1a[0:8] + sha1b[8:20] + sha1c[4:16]
53-
Array.Copy(sha1a, 0, key, 0, 8);
54-
Array.Copy(sha1b, 8, key, 8, 12);
55-
Array.Copy(sha1c, 4, key, 20, 12);
56-
57-
byte[] iv = new byte[32]; // iv = sha1a[8:20] + sha1b[0:8] + sha1c[16:20] + sha1d[0:8]
58-
Array.Copy(sha1a, 8, iv, 0, 12);
59-
Array.Copy(sha1b, 0, iv, 12, 8);
60-
Array.Copy(sha1c, 16, iv, 20, 4);
61-
Array.Copy(sha1d, 0, iv, 24, 8);
6244

6345
return new AESKeyData(key, iv);
6446
}
6547

66-
public static byte[] CalcMsgKey(byte[] data)
48+
public static byte[] CalcMsgKey(byte[] authKey, byte[] data)
6749
{
68-
byte[] msgKey = new byte[16];
69-
Array.Copy(sha1(data), 4, msgKey, 0, 16);
70-
return msgKey;
71-
}
50+
//msg_key_large = SHA256 (substr (auth_key, 88+0, 32) + plaintext + random_padding);
51+
var msgKeyLarge = SHA256(authKey.Skip(88).Take(32).Concat(data).ToArray());
7252

73-
public static byte[] CalcMsgKey(byte[] data, int offset, int limit)
74-
{
75-
byte[] msgKey = new byte[16];
76-
Array.Copy(sha1(data, offset, limit), 4, msgKey, 0, 16);
77-
return msgKey;
53+
//msg_key = substr (msg_key_large, 8, 16);
54+
return msgKeyLarge.Skip(8).Take(16).ToArray();
7855
}
7956

80-
public static byte[] sha1(byte[] data)
57+
public static byte[] SHA256(byte[] data)
8158
{
82-
using (SHA1 sha1 = new SHA1Managed())
59+
using (SHA256 sha256 = new SHA256Managed())
8360
{
84-
return sha1.ComputeHash(data);
61+
return sha256.ComputeHash(data);
8562
}
8663
}
8764

88-
public static byte[] sha1(byte[] data, int offset, int limit)
65+
public static byte[] SHA256(byte[] data, int offset, int limit)
8966
{
90-
using (SHA1 sha1 = new SHA1Managed())
67+
using (SHA256 sha256 = new SHA256Managed())
9168
{
92-
return sha1.ComputeHash(data, offset, limit);
69+
return sha256.ComputeHash(data, offset, limit);
9370
}
9471
}
9572
}

0 commit comments

Comments
 (0)