mirror of
https://github.com/wiz0u/WTelegramClient.git
synced 2025-12-06 06:52:01 +01:00
MTProto 2.0
This commit is contained in:
parent
ba90b47831
commit
21caecd164
|
|
@ -31,7 +31,9 @@ namespace WTelegram
|
|||
private Type _lastRpcResultType = typeof(object);
|
||||
private readonly List<long> _msgsToAck = new();
|
||||
private int _unexpectedSaltChange;
|
||||
|
||||
private readonly Random _random = new();
|
||||
private readonly SHA256 _sha256 = SHA256.Create();
|
||||
|
||||
public Client(Func<string,string> configProvider = null, Func<ITLObject, Task> updateHandler = null)
|
||||
{
|
||||
_config = configProvider ?? DefaultConfigOrAsk;
|
||||
|
|
@ -85,6 +87,7 @@ namespace WTelegram
|
|||
var endpoint = _session.DataCenter == null ? IPEndPoint.Parse(Config("server_address"))
|
||||
: new IPEndPoint(IPAddress.Parse(_session.DataCenter.ip_address), _session.DataCenter.port);
|
||||
Helpers.Log(2, $"Connecting to {endpoint}...");
|
||||
//TODO: maintain different connections/sessions to different DCs for main API/file download/file upload?
|
||||
_tcpClient = new TcpClient(endpoint.AddressFamily);
|
||||
await _tcpClient.ConnectAsync(endpoint.Address, endpoint.Port);
|
||||
_networkStream = _tcpClient.GetStream();
|
||||
|
|
@ -164,28 +167,42 @@ namespace WTelegram
|
|||
}
|
||||
else
|
||||
{
|
||||
//TODO: implement MTProto 2.0
|
||||
using var clearStream = new MemoryStream(1024);
|
||||
using var clearWriter = new BinaryWriter(clearStream, Encoding.UTF8);
|
||||
clearWriter.Write(_session.Salt); // int64 salt
|
||||
clearWriter.Write(_session.Id); // int64 session_id
|
||||
clearWriter.Write(msgId); // int64 message_id
|
||||
clearWriter.Write(seqno); // int32 msg_seqno
|
||||
clearWriter.Write(0); // int32 message_data_length (to be patched)
|
||||
var typeName = msgSerializer(clearWriter); // bytes message_data
|
||||
#if MTPROTO1
|
||||
const int prepend = 0;
|
||||
#else
|
||||
const int prepend = 32;
|
||||
clearWriter.Write(_session.AuthKey, 88, prepend);
|
||||
#endif
|
||||
clearWriter.Write(_session.Salt); // int64 salt
|
||||
clearWriter.Write(_session.Id); // int64 session_id
|
||||
clearWriter.Write(msgId); // int64 message_id
|
||||
clearWriter.Write(seqno); // int32 msg_seqno
|
||||
clearWriter.Write(0); // int32 message_data_length (to be patched)
|
||||
var typeName = msgSerializer(clearWriter); // bytes message_data
|
||||
Helpers.Log(1, $"Sending {typeName,-50} #{(short)msgId.GetHashCode():X4}");
|
||||
int clearLength = (int)clearStream.Length; // length before padding (= 32 + message_data_length)
|
||||
int clearLength = (int)clearStream.Length - prepend; // length before padding (= 32 + message_data_length)
|
||||
int padding = (0x7FFFFFF0 - clearLength) % 16;
|
||||
clearStream.SetLength(clearLength + padding);
|
||||
#if !MTPROTO1
|
||||
padding += _random.Next(1, 64) * 16; // MTProto 2.0 padding must be between 12..1024 with total length divisible by 16
|
||||
#endif
|
||||
clearStream.SetLength(prepend + clearLength + padding);
|
||||
byte[] clearBuffer = clearStream.GetBuffer();
|
||||
BinaryPrimitives.WriteInt32LittleEndian(clearBuffer.AsSpan(28), clearLength - 32); // patch message_data_length
|
||||
RNG.GetBytes(clearBuffer, clearLength, padding);
|
||||
var clearSha1 = SHA1.HashData(clearBuffer.AsSpan(0, clearLength)); // padding excluded from computation!
|
||||
byte[] encrypted_data = EncryptDecryptMessage(clearBuffer.AsSpan(0, clearLength + padding), true, _session.AuthKey, clearSha1);
|
||||
BinaryPrimitives.WriteInt32LittleEndian(clearBuffer.AsSpan(prepend + 28), clearLength - 32); // patch message_data_length
|
||||
RNG.GetBytes(clearBuffer, prepend + clearLength, padding);
|
||||
#if MTPROTO1
|
||||
var msgKeyLarge = SHA1.HashData(clearBuffer.AsSpan(0, clearLength)); // padding excluded from computation!
|
||||
const int msgKeyOffset = 4; // msg_key = low 128-bits of SHA1(plaintext)
|
||||
#else
|
||||
var msgKeyLarge = SHA256.HashData(clearBuffer.AsSpan(0, prepend + clearLength + padding));
|
||||
const int msgKeyOffset = 8; // msg_key = middle 128-bits of SHA256(authkey_part+plaintext+padding)
|
||||
#endif
|
||||
byte[] encrypted_data = EncryptDecryptMessage(clearBuffer.AsSpan(prepend, clearLength + padding), true, _session.AuthKey, msgKeyLarge);
|
||||
|
||||
writer.Write(_session.AuthKeyID); // int64 auth_key_id
|
||||
writer.Write(clearSha1, 4, 16); // int128 msg_key = low 128-bits of SHA1(clear message body)
|
||||
writer.Write(encrypted_data); // bytes encrypted_data
|
||||
writer.Write(_session.AuthKeyID); // int64 auth_key_id
|
||||
writer.Write(msgKeyLarge, msgKeyOffset, 16); // int128 msg_key
|
||||
writer.Write(encrypted_data); // bytes encrypted_data
|
||||
}
|
||||
|
||||
var buffer = memStream.GetBuffer();
|
||||
|
|
@ -229,7 +246,12 @@ namespace WTelegram
|
|||
throw new ApplicationException($"Received a packet encrypted with unexpected key {authKeyId:X}");
|
||||
else
|
||||
{
|
||||
byte[] decrypted_data = EncryptDecryptMessage(data.AsSpan(24), false, _session.AuthKey, data[4..24]);
|
||||
#if MTPROTO1
|
||||
byte[] msgKeyLarge = data[4..24];
|
||||
#else
|
||||
byte[] msgKeyLarge = data[0..24];
|
||||
#endif
|
||||
byte[] decrypted_data = EncryptDecryptMessage(data.AsSpan(24), false, _session.AuthKey, msgKeyLarge);
|
||||
if (decrypted_data.Length < 36) // header below+ctorNb
|
||||
throw new ApplicationException($"Decrypted packet too small: {decrypted_data.Length}");
|
||||
using var reader = new BinaryReader(new MemoryStream(decrypted_data));
|
||||
|
|
@ -249,10 +271,17 @@ namespace WTelegram
|
|||
if (sessionId != _session.Id) throw new ApplicationException($"Unexpected session ID {_session.Id} != {_session.Id}");
|
||||
if ((msgId & 1) == 0) throw new ApplicationException($"Invalid server msgId {msgId}");
|
||||
if ((seqno & 1) != 0) lock(_msgsToAck) _msgsToAck.Add(msgId);
|
||||
#if MTPROTO1
|
||||
if (decrypted_data.Length - 32 - length is < 0 or > 15) throw new ApplicationException($"Unexpected decrypted message_data_length {length} / {decrypted_data.Length - 32}");
|
||||
if (!data.AsSpan(8, 16).SequenceEqual(SHA1.HashData(decrypted_data.AsSpan(0, 32 + length)).AsSpan(4)))
|
||||
throw new ApplicationException($"Mismatch between MsgKey & decrypted SHA1");
|
||||
|
||||
#else
|
||||
if (decrypted_data.Length - 32 - length is < 12 or > 1024) throw new ApplicationException($"Unexpected decrypted message_data_length {length} / {decrypted_data.Length - 32}");
|
||||
_sha256.TransformBlock(_session.AuthKey, 96, 32, null, 0);
|
||||
_sha256.TransformFinalBlock(decrypted_data, 0, decrypted_data.Length);
|
||||
if (!data.AsSpan(8, 16).SequenceEqual(_sha256.Hash.AsSpan(8, 16)))
|
||||
throw new ApplicationException($"Mismatch between MsgKey & decrypted SHA1");
|
||||
#endif
|
||||
return reader.ReadTLObject((type, obj) =>
|
||||
{
|
||||
Helpers.Log(1, $"Receiving {type.Name,-50} timestamp={_session.MsgIdToStamp(msgId)} isResponse={(msgId & 2) != 0} {(seqno == -1 ? "clearText" : "isContent")}={(seqno & 1) != 0}");
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ namespace WTelegram
|
|||
|
||||
//1)
|
||||
var nonce = new Int128(RNG);
|
||||
#if MTPROTO1
|
||||
var resPQ = await client.ReqPQ(nonce);
|
||||
#else
|
||||
var resPQ = await client.ReqPqMulti(nonce);
|
||||
#endif
|
||||
//2)
|
||||
if (resPQ.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
var fingerprint = resPQ.server_public_key_fingerprints.FirstOrDefault(PublicKeys.ContainsKey);
|
||||
|
|
@ -35,7 +39,7 @@ namespace WTelegram
|
|||
ulong p = Helpers.PQFactorize(pq);
|
||||
ulong q = pq / p;
|
||||
//4)
|
||||
var pqInnerData = new PQInnerData
|
||||
var pqInnerData = new PQInnerDataDc
|
||||
{
|
||||
pq = resPQ.pq,
|
||||
p = Helpers.ToBigEndian(p),
|
||||
|
|
@ -43,6 +47,7 @@ namespace WTelegram
|
|||
nonce = nonce,
|
||||
server_nonce = resPQ.server_nonce,
|
||||
new_nonce = new Int256(RNG),
|
||||
dc = session.DataCenter?.id ?? 0
|
||||
};
|
||||
byte[] encrypted_data;
|
||||
{ // the following code was the way TDLib did it (and seems still accepted) until they changed on 8 July 2021
|
||||
|
|
@ -116,14 +121,14 @@ namespace WTelegram
|
|||
var authKeyHash = SHA1.HashData(authKey);
|
||||
retry_id = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash); // (auth_key_aux_hash)
|
||||
//9)
|
||||
if (setClientDHparamsAnswer is not DHGenOk) throw new ApplicationException("not dh_gen_ok");
|
||||
if (setClientDHparamsAnswer.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (setClientDHparamsAnswer.server_nonce != resPQ.server_nonce) throw new ApplicationException("Server Nonce mismatch");
|
||||
if (setClientDHparamsAnswer is not DhGenOk dhGenOk) throw new ApplicationException("not dh_gen_ok");
|
||||
if (dhGenOk.nonce != nonce) throw new ApplicationException("Nonce mismatch");
|
||||
if (dhGenOk.server_nonce != resPQ.server_nonce) throw new ApplicationException("Server Nonce mismatch");
|
||||
var expected_new_nonceN = new byte[32 + 1 + 8];
|
||||
pqInnerData.new_nonce.raw.CopyTo(expected_new_nonceN, 0);
|
||||
expected_new_nonceN[32] = 1;
|
||||
Array.Copy(authKeyHash, 0, expected_new_nonceN, 33, 8); // (auth_key_aux_hash)
|
||||
if (!Enumerable.SequenceEqual(setClientDHparamsAnswer.new_nonce_hashN.raw, SHA1.HashData(expected_new_nonceN).Skip(4)))
|
||||
if (!Enumerable.SequenceEqual(dhGenOk.new_nonce_hash1.raw, SHA1.HashData(expected_new_nonceN).Skip(4)))
|
||||
throw new ApplicationException("setClientDHparamsAnswer.new_nonce_hashN mismatch");
|
||||
|
||||
session.AuthKeyID = BinaryPrimitives.ReadInt64LittleEndian(authKeyHash.AsSpan(12));
|
||||
|
|
@ -172,6 +177,9 @@ namespace WTelegram
|
|||
// We recommend checking that g_a and g_b are between 2^{2048-64} and dh_prime - 2^{2048-64} as well.
|
||||
}
|
||||
|
||||
[TLDef(0x7A19CB76)] //RSA_public_key#7a19cb76 n:bytes e:bytes = RSAPublicKey
|
||||
public partial class RSAPublicKey : ITLObject { public byte[] n, e; }
|
||||
|
||||
public static void LoadPublicKey(string pem)
|
||||
{
|
||||
using var rsa = RSA.Create();
|
||||
|
|
@ -196,23 +204,24 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||
-----END RSA PUBLIC KEY-----");
|
||||
}
|
||||
|
||||
internal static byte[] EncryptDecryptMessage(Span<byte> input, bool encrypt, byte[] authKey, byte[] clearSha1)
|
||||
internal static byte[] EncryptDecryptMessage(Span<byte> input, bool encrypt, byte[] authKey, byte[] msgKeyLarge)
|
||||
{
|
||||
// first, construct AES key & IV
|
||||
int x = encrypt ? 0 : 8;
|
||||
byte[] aes_key = new byte[32], aes_iv = new byte[32];
|
||||
using var sha1 = new SHA1Managed();
|
||||
sha1.TransformBlock(clearSha1, 4, 16, null, 0); // msgKey
|
||||
#if MTPROTO1
|
||||
using var sha1 = SHA1.Create();
|
||||
sha1.TransformBlock(msgKeyLarge, 4, 16, null, 0); // msgKey
|
||||
sha1.TransformFinalBlock(authKey, x, 32); // authKey[x:32]
|
||||
var sha1_a = sha1.Hash;
|
||||
sha1.TransformBlock(authKey, 32 + x, 16, null, 0); // authKey[32+x:16]
|
||||
sha1.TransformBlock(clearSha1, 4, 16, null, 0); // msgKey
|
||||
sha1.TransformBlock(msgKeyLarge, 4, 16, null, 0); // msgKey
|
||||
sha1.TransformFinalBlock(authKey, 48 + x, 16); // authKey[48+x:16]
|
||||
var sha1_b = sha1.Hash;
|
||||
sha1.TransformBlock(authKey, 64 + x, 32, null, 0); // authKey[64+x:32]
|
||||
sha1.TransformFinalBlock(clearSha1, 4, 16); // msgKey
|
||||
sha1.TransformFinalBlock(msgKeyLarge, 4, 16); // msgKey
|
||||
var sha1_c = sha1.Hash;
|
||||
sha1.TransformBlock(clearSha1, 4, 16, null, 0); // msgKey
|
||||
sha1.TransformBlock(msgKeyLarge, 4, 16, null, 0); // msgKey
|
||||
sha1.TransformFinalBlock(authKey, 96 + x, 32); // authKey[96+x:32]
|
||||
var sha1_d = sha1.Hash;
|
||||
Array.Copy(sha1_a, 0, aes_key, 0, 8);
|
||||
|
|
@ -222,6 +231,21 @@ Slv8kg9qv1m6XHVQY3PnEw+QQtqSIXklHwIDAQAB
|
|||
Array.Copy(sha1_b, 0, aes_iv, 12, 8);
|
||||
Array.Copy(sha1_c, 16, aes_iv, 20, 4);
|
||||
Array.Copy(sha1_d, 0, aes_iv, 24, 8);
|
||||
#else
|
||||
using var sha256 = SHA256.Create();
|
||||
sha256.TransformBlock(msgKeyLarge, 8, 16, null, 0); // msgKey
|
||||
sha256.TransformFinalBlock(authKey, x, 36); // authKey[x:36]
|
||||
var sha256_a = sha256.Hash;
|
||||
sha256.TransformBlock(authKey, 40 + x, 36, null, 0); // authKey[40+x:36]
|
||||
sha256.TransformFinalBlock(msgKeyLarge, 8, 16); // msgKey
|
||||
var sha256_b = sha256.Hash;
|
||||
Array.Copy(sha256_a, 0, aes_key, 0, 8);
|
||||
Array.Copy(sha256_b, 8, aes_key, 8, 16);
|
||||
Array.Copy(sha256_a, 24, aes_key, 24, 8);
|
||||
Array.Copy(sha256_b, 0, aes_iv, 0, 8);
|
||||
Array.Copy(sha256_a, 8, aes_iv, 8, 16);
|
||||
Array.Copy(sha256_b, 24, aes_iv, 24, 8);
|
||||
#endif
|
||||
|
||||
return AES_IGE_EncryptDecrypt(input, aes_key, aes_iv, encrypt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,16 +29,15 @@ namespace WTelegram
|
|||
await File.WriteAllBytesAsync("TL.MTProto.json", await http.GetByteArrayAsync("https://core.telegram.org/schema/mtproto-json"));
|
||||
await File.WriteAllBytesAsync("TL.Schema.json", await http.GetByteArrayAsync("https://core.telegram.org/schema/json"));
|
||||
await File.WriteAllBytesAsync("TL.Secret.json", await http.GetByteArrayAsync("https://core.telegram.org/schema/end-to-end-json"));
|
||||
FromJson("TL.MTProto.json", "TL.MTProto.cs", @"TL.Table.cs", true);
|
||||
FromJson("TL.MTProto.json", "TL.MTProto.cs", @"TL.Table.cs");
|
||||
FromJson("TL.Schema.json", "TL.Schema.cs", @"TL.Table.cs");
|
||||
FromJson("TL.Secret.json", "TL.Secret.cs", @"TL.Table.cs");
|
||||
}
|
||||
|
||||
public void FromJson(string jsonPath, string outputCs, string tableCs = null, bool legacy = false)
|
||||
public void FromJson(string jsonPath, string outputCs, string tableCs = null)
|
||||
{
|
||||
Console.WriteLine("Parsing " + jsonPath);
|
||||
var schema = JsonSerializer.Deserialize<SchemaJson>(File.ReadAllText(jsonPath));
|
||||
if (legacy) InjectLegacy(schema);
|
||||
using var sw = File.CreateText(outputCs);
|
||||
sw.WriteLine("// This file is (mainly) generated automatically using the Generator class");
|
||||
sw.WriteLine("using System;");
|
||||
|
|
@ -147,34 +146,6 @@ namespace WTelegram
|
|||
if (tableCs != null) UpdateTable(jsonPath, tableCs, methods);
|
||||
}
|
||||
|
||||
private static void InjectLegacy(SchemaJson schema)
|
||||
{
|
||||
foreach (var c in schema.constructors.Where(c => c.type == "P_Q_inner_data"))
|
||||
c.predicate = c.predicate[..^2] + "DC";
|
||||
var add = new Constructor { id = ID(0x83C95AEC), predicate = "p_q_inner_data", type = "P_Q_inner_data",
|
||||
@params = Params("pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256") };
|
||||
schema.constructors.Insert(schema.constructors.FindIndex(c => c.type == add.type), add);
|
||||
add = new Constructor { id = ID(0x79CB045D), predicate = "server_DH_params_fail", type = "Server_DH_Params",
|
||||
@params = Params("nonce:int128 server_nonce:int128 new_nonce_hash:int128") };
|
||||
schema.constructors.Insert(schema.constructors.FindIndex(c => c.type == add.type), add);
|
||||
add = new Constructor { id = ID(0x7A19CB76), predicate = "RSA_public_key", type = "RSAPublicKey",
|
||||
@params = Params("n:bytes e:bytes") };
|
||||
schema.constructors.Insert(schema.constructors.FindIndex(c => c.type == "DestroyAuthKeyRes"), add);
|
||||
foreach (var c in schema.constructors.Where(c => c.type == "Set_client_DH_params_answer"))
|
||||
{
|
||||
c.predicate = "DH" + c.predicate[2..];
|
||||
c.@params[2].name = "new_nonce_hashN";
|
||||
}
|
||||
schema.constructors.Find(c => c.predicate == "future_salts").@params[2].type = "Vector<FutureSalt>";
|
||||
var addm = new Method { id = ID(0x60469778), method= "req_PQ", type = "ResPQ",
|
||||
@params = Params("nonce:int128") };
|
||||
schema.methods.Insert(0, addm);
|
||||
|
||||
static string ID(uint id) => ((int)id).ToString();
|
||||
static Param[] Params(string args)
|
||||
=> args.Split(' ').Select(s => { var nt = s.Split(':'); return new Param { name = nt[0], type = nt[1] }; }).ToArray();
|
||||
}
|
||||
|
||||
void WriteTypeInfo(StreamWriter sw, TypeInfo typeInfo, string layerPrefix, bool isMethod)
|
||||
{
|
||||
var parentClass = typeInfo.NeedAbstract != 0 ? typeInfo.ReturnName : "ITLObject";
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ namespace WTelegram
|
|||
internal class Session
|
||||
{
|
||||
public long AuthKeyID;
|
||||
public byte[] AuthKey;
|
||||
public byte[] AuthKey; // 2048-bit = 256 bytes
|
||||
public long Salt;
|
||||
public long Id;
|
||||
public int Seqno;
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@ namespace TL
|
|||
public long[] server_public_key_fingerprints;
|
||||
}
|
||||
|
||||
[TLDef(0x83C95AEC)] //p_q_inner_data#83c95aec pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data
|
||||
public partial class PQInnerData : ITLObject
|
||||
public abstract partial class PQInnerData : ITLObject
|
||||
{
|
||||
public byte[] pq;
|
||||
public byte[] p;
|
||||
|
|
@ -22,25 +21,21 @@ namespace TL
|
|||
public Int128 nonce;
|
||||
public Int128 server_nonce;
|
||||
public Int256 new_nonce;
|
||||
}
|
||||
[TLDef(0xA9F55F95)] //p_q_inner_data_DC#a9f55f95 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data
|
||||
public partial class PQInnerDataDC : PQInnerData { public int dc; }
|
||||
[TLDef(0x56FDDF88)] //p_q_inner_data_temp_DC#56fddf88 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data
|
||||
public partial class PQInnerDataTempDC : PQInnerData
|
||||
{
|
||||
public int dc;
|
||||
public int expires_in; // seconds
|
||||
}
|
||||
[TLDef(0xA9F55F95)] //p_q_inner_data_dc#a9f55f95 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data
|
||||
public partial class PQInnerDataDc : PQInnerData { }
|
||||
[TLDef(0x56FDDF88)] //p_q_inner_data_temp_dc#56fddf88 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data
|
||||
public partial class PQInnerDataTempDc : PQInnerData { public int expires_in; }
|
||||
|
||||
public abstract partial class ServerDHParams : ITLObject
|
||||
public abstract partial class ServerDHParams : ITLObject { }
|
||||
[TLDef(0xD0E8075C)] //server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params
|
||||
public partial class ServerDHParamsOk : ServerDHParams
|
||||
{
|
||||
public Int128 nonce;
|
||||
public Int128 server_nonce;
|
||||
public byte[] encrypted_answer;
|
||||
}
|
||||
[TLDef(0x79CB045D)] //server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params
|
||||
public partial class ServerDHParamsFail : ServerDHParams { public Int128 new_nonce_hash; }
|
||||
[TLDef(0xD0E8075C)] //server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params
|
||||
public partial class ServerDHParamsOk : ServerDHParams { public byte[] encrypted_answer; }
|
||||
|
||||
[TLDef(0xB5890DBA)] //server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:bytes g_a:bytes server_time:int = Server_DH_inner_data
|
||||
public partial class ServerDHInnerData : ITLObject
|
||||
|
|
@ -66,14 +61,13 @@ namespace TL
|
|||
{
|
||||
public Int128 nonce;
|
||||
public Int128 server_nonce;
|
||||
public Int128 new_nonce_hashN; // 16 low order bytes from SHA1(new_nonce + (01=ok, 02=retry, 03=fail) + 8 high order bytes from SHA1(auth_key))
|
||||
}
|
||||
[TLDef(0x3BCBF734)] //DH_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hashN:int128 = Set_client_DH_params_answer
|
||||
public partial class DHGenOk : SetClientDHParamsAnswer { }
|
||||
[TLDef(0x46DC1FB9)] //DH_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hashN:int128 = Set_client_DH_params_answer
|
||||
public partial class DHGenRetry : SetClientDHParamsAnswer { }
|
||||
[TLDef(0xA69DAE02)] //DH_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hashN:int128 = Set_client_DH_params_answer
|
||||
public partial class DHGenFail : SetClientDHParamsAnswer { }
|
||||
[TLDef(0x3BCBF734)] //dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer
|
||||
public partial class DhGenOk : SetClientDHParamsAnswer { public Int128 new_nonce_hash1; }
|
||||
[TLDef(0x46DC1FB9)] //dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer
|
||||
public partial class DhGenRetry : SetClientDHParamsAnswer { public Int128 new_nonce_hash2; }
|
||||
[TLDef(0xA69DAE02)] //dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer
|
||||
public partial class DhGenFail : SetClientDHParamsAnswer { public Int128 new_nonce_hash3; }
|
||||
|
||||
[TLDef(0x75A3F765)] //bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner
|
||||
public partial class BindAuthKeyInner : ITLObject
|
||||
|
|
@ -120,7 +114,7 @@ namespace TL
|
|||
public long salt;
|
||||
}
|
||||
|
||||
[TLDef(0xAE500895)] //future_salts#ae500895 req_msg_id:long now:int salts:Vector<FutureSalt> = FutureSalts
|
||||
[TLDef(0xAE500895)] //future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts
|
||||
public partial class FutureSalts : ITLObject
|
||||
{
|
||||
public long req_msg_id;
|
||||
|
|
@ -221,13 +215,6 @@ namespace TL
|
|||
public int status;
|
||||
}
|
||||
|
||||
[TLDef(0x7A19CB76)] //RSA_public_key#7a19cb76 n:bytes e:bytes = RSAPublicKey
|
||||
public partial class RSAPublicKey : ITLObject
|
||||
{
|
||||
public byte[] n;
|
||||
public byte[] e;
|
||||
}
|
||||
|
||||
public abstract partial class DestroyAuthKeyRes : ITLObject { }
|
||||
[TLDef(0xF660E1D4)] //destroy_auth_key_ok#f660e1d4 = DestroyAuthKeyRes
|
||||
public partial class DestroyAuthKeyOk : DestroyAuthKeyRes { }
|
||||
|
|
@ -244,15 +231,6 @@ namespace WTelegram // ---functions---
|
|||
|
||||
public partial class Client
|
||||
{
|
||||
//req_PQ#60469778 nonce:int128 = ResPQ
|
||||
public Task<ResPQ> ReqPQ(Int128 nonce)
|
||||
=> CallAsync<ResPQ>(writer =>
|
||||
{
|
||||
writer.Write(0x60469778);
|
||||
writer.Write(nonce);
|
||||
return "ReqPQ";
|
||||
});
|
||||
|
||||
//req_pq_multi#be7e8ef1 nonce:int128 = ResPQ
|
||||
public Task<ResPQ> ReqPqMulti(Int128 nonce)
|
||||
=> CallAsync<ResPQ>(writer =>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ namespace TL
|
|||
{
|
||||
static partial class Schema
|
||||
{
|
||||
public const int Layer = 121; // fetched 09/08/2021 22:59:12
|
||||
public const int Layer = 121; // fetched 10/08/2021 11:46:24
|
||||
public const int VectorCtor = 0x1CB5C415;
|
||||
public const int NullCtor = 0x56730BCC;
|
||||
|
||||
|
|
@ -14,16 +14,14 @@ namespace TL
|
|||
{
|
||||
// from TL.MTProto:
|
||||
[0x05162463] = typeof(ResPQ),
|
||||
[0x83C95AEC] = typeof(PQInnerData),
|
||||
[0xA9F55F95] = typeof(PQInnerDataDC),
|
||||
[0x56FDDF88] = typeof(PQInnerDataTempDC),
|
||||
[0x79CB045D] = typeof(ServerDHParamsFail),
|
||||
[0xA9F55F95] = typeof(PQInnerDataDc),
|
||||
[0x56FDDF88] = typeof(PQInnerDataTempDc),
|
||||
[0xD0E8075C] = typeof(ServerDHParamsOk),
|
||||
[0xB5890DBA] = typeof(ServerDHInnerData),
|
||||
[0x6643B654] = typeof(ClientDHInnerData),
|
||||
[0x3BCBF734] = typeof(DHGenOk),
|
||||
[0x46DC1FB9] = typeof(DHGenRetry),
|
||||
[0xA69DAE02] = typeof(DHGenFail),
|
||||
[0x3BCBF734] = typeof(DhGenOk),
|
||||
[0x46DC1FB9] = typeof(DhGenRetry),
|
||||
[0xA69DAE02] = typeof(DhGenFail),
|
||||
[0x75A3F765] = typeof(BindAuthKeyInner),
|
||||
[0xF35C6D01] = typeof(RpcResult),
|
||||
[0x2144CA19] = typeof(RpcError),
|
||||
|
|
@ -49,7 +47,6 @@ namespace TL
|
|||
[0x8CC0D131] = typeof(MsgsAllInfo),
|
||||
[0x276D3EC6] = typeof(MsgDetailedInfo),
|
||||
[0x809DB6DF] = typeof(MsgNewDetailedInfo),
|
||||
[0x7A19CB76] = typeof(RSAPublicKey),
|
||||
[0xF660E1D4] = typeof(DestroyAuthKeyOk),
|
||||
[0x0A9F2259] = typeof(DestroyAuthKeyNone),
|
||||
[0xEA109B13] = typeof(DestroyAuthKeyFail),
|
||||
|
|
|
|||
Loading…
Reference in a new issue