Encryption class public + Methods table
Some checks failed
Dev build / build (push) Has been cancelled

This commit is contained in:
Wizou 2025-10-10 20:27:42 +02:00
parent a5323eaa86
commit 48d005b605
3 changed files with 23 additions and 15 deletions

View file

@ -32,6 +32,7 @@ public class MTProtoGenerator : IIncrementalGenerator
var nullables = LoadNullables(layer); var nullables = LoadNullables(layer);
var namespaces = new Dictionary<string, Dictionary<string, string>>(); // namespace,class,methods var namespaces = new Dictionary<string, Dictionary<string, string>>(); // namespace,class,methods
var tableTL = new StringBuilder(); var tableTL = new StringBuilder();
var methodsTL = new StringBuilder();
var source = new StringBuilder(); var source = new StringBuilder();
source source
.AppendLine("using System;") .AppendLine("using System;")
@ -46,6 +47,9 @@ public class MTProtoGenerator : IIncrementalGenerator
tableTL tableTL
.AppendLine("\t\tpublic static readonly Dictionary<uint, Func<BinaryReader, IObject>> Table = new()") .AppendLine("\t\tpublic static readonly Dictionary<uint, Func<BinaryReader, IObject>> Table = new()")
.AppendLine("\t\t{"); .AppendLine("\t\t{");
methodsTL
.AppendLine("\t\tpublic static readonly Dictionary<uint, Func<BinaryReader, IObject>> Methods = new()")
.AppendLine("\t\t{");
foreach (var classDecl in unit.classes) foreach (var classDecl in unit.classes)
{ {
@ -86,8 +90,13 @@ public class MTProtoGenerator : IIncrementalGenerator
} }
if (id == 0x3072CFA1) // GzipPacked if (id == 0x3072CFA1) // GzipPacked
tableTL.AppendLine($"\t\t\t[0x{id:X8}] = reader => (IObject)reader.ReadTLGzipped(typeof(IObject)),"); tableTL.AppendLine($"\t\t\t[0x{id:X8}] = reader => (IObject)reader.ReadTLGzipped(typeof(IObject)),");
else if (name != "Null" && (ns != "TL.Methods" || name == "Ping")) else if (name != "Null")
{
if (ns == "TL.Methods")
methodsTL.AppendLine($"\t\t\t[0x{id:X8}] = {(ns == "TL" ? "" : ns + '.')}{name}{(symbol.IsGenericType ? "<IObject>" : "")}.ReadTL,");
if (ns != "TL.Methods" || name == "Ping")
tableTL.AppendLine($"\t\t\t[0x{id:X8}] = {(ns == "TL" ? "" : ns + '.')}{name}.ReadTL,"); tableTL.AppendLine($"\t\t\t[0x{id:X8}] = {(ns == "TL" ? "" : ns + '.')}{name}.ReadTL,");
}
var override_ = symbol.BaseType == object_ ? "" : "override "; var override_ = symbol.BaseType == object_ ? "" : "override ";
if (name == "Messages_AffectedMessages") override_ = "virtual "; if (name == "Messages_AffectedMessages") override_ = "virtual ";
//if (symbol.Constructors[0].IsImplicitlyDeclared) //if (symbol.Constructors[0].IsImplicitlyDeclared)
@ -213,7 +222,8 @@ public class MTProtoGenerator : IIncrementalGenerator
foreach (var nullable in nullables) foreach (var nullable in nullables)
tableTL.AppendLine($"\t\t\t[0x{nullable.Value:X8}] = null,"); tableTL.AppendLine($"\t\t\t[0x{nullable.Value:X8}] = null,");
tableTL.AppendLine("\t\t};"); tableTL.AppendLine("\t\t};");
namespaces["TL"]["Layer"] = tableTL.ToString(); methodsTL.AppendLine("\t\t};");
namespaces["TL"]["Layer"] = tableTL.ToString() + methodsTL.ToString();
foreach (var namesp in namespaces) foreach (var namesp in namespaces)
{ {
source.Append("namespace ").AppendLine(namesp.Key).Append('{'); source.Append("namespace ").AppendLine(namesp.Key).Append('{');

View file

@ -185,10 +185,6 @@ namespace WTelegram
return Console.ReadLine(); return Console.ReadLine();
} }
/// <summary>Load a specific Telegram server public key</summary>
/// <param name="pem">A string starting with <c>-----BEGIN RSA PUBLIC KEY-----</c></param>
public static void LoadPublicKey(string pem) => Encryption.LoadPublicKey(pem);
/// <summary>Builds a structure that is used to validate a 2FA password</summary> /// <summary>Builds a structure that is used to validate a 2FA password</summary>
/// <param name="accountPassword">Password validation configuration. You can obtain this via <c>Account_GetPassword</c> or through OnOther as part of the login process</param> /// <param name="accountPassword">Password validation configuration. You can obtain this via <c>Account_GetPassword</c> or through OnOther as part of the login process</param>
/// <param name="password">The password to validate</param> /// <param name="password">The password to validate</param>
@ -358,7 +354,7 @@ namespace WTelegram
if (await stream.FullReadAsync(data, 4, ct) != 4) if (await stream.FullReadAsync(data, 4, ct) != 4)
throw new WTException(ConnectionShutDown); throw new WTException(ConnectionShutDown);
#if OBFUSCATION #if OBFUSCATION
_recvCtr.EncryptDecrypt(data, 4); _recvCtr.EncryptDecrypt(data.AsSpan(0, 4));
#endif #endif
int payloadLen = BinaryPrimitives.ReadInt32LittleEndian(data); int payloadLen = BinaryPrimitives.ReadInt32LittleEndian(data);
if (payloadLen <= 0) if (payloadLen <= 0)
@ -370,7 +366,7 @@ namespace WTelegram
if (await stream.FullReadAsync(data, payloadLen, ct) != payloadLen) if (await stream.FullReadAsync(data, payloadLen, ct) != payloadLen)
throw new WTException("Could not read frame data : Connection shut down"); throw new WTException("Could not read frame data : Connection shut down");
#if OBFUSCATION #if OBFUSCATION
_recvCtr.EncryptDecrypt(data, payloadLen); _recvCtr.EncryptDecrypt(data.AsSpan(0, payloadLen));
#endif #endif
obj = ReadFrame(data, payloadLen); obj = ReadFrame(data, payloadLen);
} }
@ -1526,7 +1522,7 @@ namespace WTelegram
int frameLength = (int)memStream.Length; int frameLength = (int)memStream.Length;
BinaryPrimitives.WriteInt32LittleEndian(buffer, frameLength - 4); // patch payload_len with correct value BinaryPrimitives.WriteInt32LittleEndian(buffer, frameLength - 4); // patch payload_len with correct value
#if OBFUSCATION #if OBFUSCATION
_sendCtr?.EncryptDecrypt(buffer, frameLength); _sendCtr?.EncryptDecrypt(buffer.AsSpan(0, frameLength));
#endif #endif
if (_networkStream != null) if (_networkStream != null)
await _networkStream.WriteAsync(buffer, 0, frameLength); await _networkStream.WriteAsync(buffer, 0, frameLength);

View file

@ -13,7 +13,7 @@ using static WTelegram.Compat;
namespace WTelegram namespace WTelegram
{ {
internal static class Encryption public static class Encryption
{ {
private static readonly Dictionary<long, RSAPublicKey> PublicKeys = []; private static readonly Dictionary<long, RSAPublicKey> PublicKeys = [];
internal static readonly RandomNumberGenerator RNG = RandomNumberGenerator.Create(); internal static readonly RandomNumberGenerator RNG = RandomNumberGenerator.Create();
@ -237,6 +237,8 @@ namespace WTelegram
throw new WTException("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}"); throw new WTException("g^a or g^b is not between 2^{2048-64} and dh_prime - 2^{2048-64}");
} }
/// <summary>Load a specific Telegram server public key</summary>
/// <param name="pem">A string starting with <c>-----BEGIN RSA PUBLIC KEY-----</c></param>
public static void LoadPublicKey(string pem) public static void LoadPublicKey(string pem)
{ {
using var rsa = RSA.Create(); using var rsa = RSA.Create();
@ -319,7 +321,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
} }
#if OBFUSCATION #if OBFUSCATION
internal sealed class AesCtr(byte[] key, byte[] ivec) : IDisposable public sealed class AesCtr(byte[] key, byte[] ivec) : IDisposable
{ {
readonly ICryptoTransform _encryptor = AesECB.CreateEncryptor(key, null); readonly ICryptoTransform _encryptor = AesECB.CreateEncryptor(key, null);
readonly byte[] _ecount = new byte[16]; readonly byte[] _ecount = new byte[16];
@ -327,9 +329,9 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
public void Dispose() => _encryptor.Dispose(); public void Dispose() => _encryptor.Dispose();
public void EncryptDecrypt(byte[] buffer, int length) public void EncryptDecrypt(Span<byte> buffer)
{ {
for (int i = 0; i < length; i++) for (int i = 0; i < buffer.Length; i++)
{ {
if (_num == 0) if (_num == 0)
{ {
@ -373,7 +375,7 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
var sendCtr = new AesCtr(sendKey, sendIV); var sendCtr = new AesCtr(sendKey, sendIV);
var recvCtr = new AesCtr(recvKey, recvIV); var recvCtr = new AesCtr(recvKey, recvIV);
var encrypted = (byte[])preamble.Clone(); var encrypted = (byte[])preamble.Clone();
sendCtr.EncryptDecrypt(encrypted, 64); sendCtr.EncryptDecrypt(encrypted);
for (int i = 56; i < 64; i++) for (int i = 56; i < 64; i++)
preamble[i] = encrypted[i]; preamble[i] = encrypted[i];
return (sendCtr, recvCtr, preamble); return (sendCtr, recvCtr, preamble);