diff --git a/Examples/Program_SecretChats.cs b/Examples/Program_SecretChats.cs index 057ac3e..19c565e 100644 --- a/Examples/Program_SecretChats.cs +++ b/Examples/Program_SecretChats.cs @@ -67,7 +67,6 @@ Type a command, or a message to send to the active secret chat:"); } else if (ActiveChat == null) Console.WriteLine("No active secret chat"); else await Secrets.SendMessage(ActiveChat, new TL.Layer73.DecryptedMessage { message = line, random_id = WTelegram.Helpers.RandomLong() }); - } catch (Exception ex) { diff --git a/src/Client.cs b/src/Client.cs index 10c61c4..4d4f23a 100644 --- a/src/Client.cs +++ b/src/Client.cs @@ -1247,9 +1247,12 @@ namespace WTelegram internal async Task InvokeBare(IMethod request) { if (_bareRpc != null) throw new ApplicationException("A bare request is already undergoing"); + retry: _bareRpc = new Rpc { type = typeof(T) }; await SendAsync(request, false, _bareRpc); - return (T)await _bareRpc.Task; + var result = await _bareRpc.Task; + if (result is ReactorError) goto retry; + return (T)result; } /// Call the given TL method (You shouldn't need to use this method directly) diff --git a/src/Encryption.cs b/src/Encryption.cs index 3f490c0..c7b857e 100644 --- a/src/Encryption.cs +++ b/src/Encryption.cs @@ -526,13 +526,15 @@ j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB #endif } + /// Stream for encryption/decryption of AES-256 with infinite garble extension (IGE) public class AES_IGE_Stream : Helpers.IndirectStream { private readonly ICryptoTransform aesCrypto; private readonly byte[] prevBytes; + /// Decryption of AES-256 IGE file with key/iv obtained from media structure public AES_IGE_Stream(Stream stream, DecryptedMessageMedia media) : this(stream, media.SizeKeyIV) { } - public AES_IGE_Stream(Stream innerStream, (int size, byte[] key, byte[] iv) t) : this(innerStream, t.key, t.iv) { ContentLength = t.size; } + public AES_IGE_Stream(Stream stream, (int size, byte[] key, byte[] iv) t) : this(stream, t.key, t.iv) { ContentLength = t.size; } public AES_IGE_Stream(Stream stream, byte[] key, byte[] iv, bool encrypt = false) : base(stream) { aesCrypto = encrypt ? Encryption.AesECB.CreateEncryptor(key, null) : Encryption.AesECB.CreateDecryptor(key, null); diff --git a/src/SecretChats.cs b/src/SecretChats.cs index 1fb1987..89d5d3a 100644 --- a/src/SecretChats.cs +++ b/src/SecretChats.cs @@ -264,7 +264,7 @@ namespace WTelegram /// Secret Chat ID /// The pre-filled DecryptedMessage or DecryptedMessageService to send /// Send encrypted message without a notification - /// Optional file attachment + /// Optional file attachment. See method UploadFile /// Confirmation of sent message public async Task SendMessage(int chatId, DecryptedMessageBase msg, bool silent = false, InputEncryptedFileBase file = null) { @@ -569,7 +569,12 @@ namespace WTelegram } } - public async Task UploadFile(Stream stream, DecryptedMessageMedia media) + /// Upload a file to Telegram in encrypted form + /// Content of the file to upload. This method close/dispose the stream + /// The associated media structure that will be updated with file size and the random AES key/iv + /// (optional) Callback for tracking the progression of the transfer + /// the uploaded file info that should be passed to method SendMessage + public async Task UploadFile(Stream stream, DecryptedMessageMedia media, Client.ProgressCallback progress = null) { byte[] aes_key = new byte[32], aes_iv = new byte[32]; RNG.GetBytes(aes_key); @@ -579,12 +584,11 @@ namespace WTelegram using var md5 = MD5.Create(); md5.TransformBlock(aes_key, 0, 32, null, 0); var res = md5.TransformFinalBlock(aes_iv, 0, 32); - var digest = md5.Hash; - long fingerprint = BinaryPrimitives.ReadInt64LittleEndian(digest); + long fingerprint = BinaryPrimitives.ReadInt64LittleEndian(md5.Hash); fingerprint ^= fingerprint >> 32; using var ige = new AES_IGE_Stream(stream, aes_key, aes_iv, true); - return await client.UploadFileAsync(ige, null) switch + return await client.UploadFileAsync(ige, null, progress) switch { InputFile ifl => new InputEncryptedFileUploaded { id = ifl.id, parts = ifl.parts, md5_checksum = ifl.md5_checksum, key_fingerprint = (int)fingerprint }, InputFileBig ifb => new InputEncryptedFileBigUploaded { id = ifb.id, parts = ifb.parts, key_fingerprint = (int)fingerprint },