public byte[] Decrypt(byte[] data) { if (DecryptCountBuf == null) { DecryptCountBuf = new byte[16]; DecryptNum = 0; } return(Utils.AES_ctr128_encrypt(data, DecryptKey, ref DecryptIV, ref DecryptCountBuf, ref DecryptNum)); }
public byte[] Encrypt(byte[] data) { if (EncryptCountBuf == null) { EncryptCountBuf = new byte[16]; EncryptNum = 0; } return(Utils.AES_ctr128_encrypt(data, EncryptKey, ref EncryptIV, ref EncryptCountBuf, ref EncryptNum)); }
private TLUploadFileBase GetCdnFile(TLUploadFileCdnRedirect redirect, TLFileLocation location, int offset, int limit, out TLRPCError er, out bool isCanceled) { var manualResetEvent = new ManualResetEvent(false); TLUploadFileBase result = null; TLRPCError outError = null; var outIsCanceled = false; var req = new TLUploadGetCdnFile(); req.FileToken = redirect.FileToken; req.Limit = limit; req.Offset = offset; _mtProtoService.SendRequestAsync <TLUploadCdnFileBase>("upload.getCdnFile", req, redirect.DCId, true, callback => { if (callback is TLUploadCdnFile file) { var iv = redirect.EncryptionIV; var counter = offset / 16; iv[15] = (byte)(counter & 0xFF); iv[14] = (byte)((counter >> 8) & 0xFF); iv[13] = (byte)((counter >> 16) & 0xFF); iv[12] = (byte)((counter >> 24) & 0xFF); var key = CryptographicBuffer.CreateFromByteArray(redirect.EncryptionKey); var ecount_buf = new byte[0]; var num = 0u; var bytes = Utils.AES_ctr128_encrypt(file.Bytes, key, ref iv, ref ecount_buf, ref num); result = new TLUploadFile { Bytes = bytes }; manualResetEvent.Set(); _statsService.IncrementReceivedBytesCount(_mtProtoService.NetworkType, _dataType, file.Bytes.Length + 4); } else if (callback is TLUploadCdnFileReuploadNeeded reupload) { result = ReuploadFile(redirect, reupload.RequestToken, location, offset, limit, out outError, out outIsCanceled); while (result == null) { result = ReuploadFile(redirect, reupload.RequestToken, location, offset, limit, out outError, out outIsCanceled); if (outIsCanceled) { break; } } manualResetEvent.Set(); } }, error => { outError = error; if (error.CodeEquals(TLErrorCode.INTERNAL) || (error.CodeEquals(TLErrorCode.BAD_REQUEST) && (error.TypeEquals(TLErrorType.LOCATION_INVALID) || error.TypeEquals(TLErrorType.VOLUME_LOC_NOT_FOUND))) || (error.CodeEquals(TLErrorCode.NOT_FOUND) && error.ErrorMessage != null && error.ErrorMessage.ToString().StartsWith("Incorrect dhGen"))) { outIsCanceled = true; manualResetEvent.Set(); return; } int delay; lock (_randomRoot) { delay = _random.Next(1000, 3000); } Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set()); }); manualResetEvent.WaitOne(20 * 1000); er = outError; isCanceled = outIsCanceled; return(result); }
private void OnDownloading(object state) { DownloadablePart part = null; lock (_itemsSyncRoot) { for (var i = 0; i < _items.Count; i++) { var item = _items[i]; if (item.IsCancelled) { _items.RemoveAt(i--); try { _eventAggregator.Publish(new DownloadingCanceledEventArgs(item)); } catch (Exception e) { TLUtils.WriteException(e); } } } foreach (var item in _items) { part = item.Parts.FirstOrDefault(x => x.Status == PartStatus.Ready); if (part != null) { part.Status = PartStatus.Processing; break; } } } if (part == null) { var currentWorker = (Worker)state; currentWorker.Stop(); return; } TLRPCError error; bool canceled; do { TLUploadFileBase result; if (part.ParentItem.CdnRedirect != null) { result = GetCdnFile(part.ParentItem.CdnRedirect, part.ParentItem.Location, part.Offset, part.Limit, out error, out canceled); } else { result = GetFile(part.ParentItem.Location, part.Offset, part.Limit, out error, out canceled); } if (result is TLUploadFileCdnRedirect redirect) { part.ParentItem.CdnRedirect = redirect; part.ParentItem.CdnHashes = redirect.CdnFileHashes.ToDictionary(x => x.Offset, x => x); continue; } else { part.File = result as TLUploadFile; } if (canceled) { lock (_itemsSyncRoot) { part.ParentItem.IsCancelled = true; part.Status = PartStatus.Processed; _items.Remove(part.ParentItem); } return; } } while (part.File == null); // indicate progress // indicate complete bool isComplete; bool isCanceled; var progress = 0.0; lock (_itemsSyncRoot) { part.Status = PartStatus.Processed; var data = part.File.Bytes; if (data.Length < part.Limit && (part.Number + 1) != part.ParentItem.Parts.Count) { var complete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); if (!complete) { var emptyBufferSize = part.Limit - data.Length; var position = data.Length; var missingPart = new DownloadablePart(part.ParentItem, position, emptyBufferSize, -part.Number); var currentItemIndex = part.ParentItem.Parts.IndexOf(part); part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); } } else if (data.Length == part.Limit && (part.Number + 1) == part.ParentItem.Parts.Count) { var currentItemIndex = part.ParentItem.Parts.IndexOf(part); var missingPart = new DownloadablePart(part.ParentItem, part.Offset + part.Limit, part.Limit, currentItemIndex + 1); part.ParentItem.Parts.Insert(currentItemIndex + 1, missingPart); } isCanceled = part.ParentItem.IsCancelled; isComplete = part.ParentItem.Parts.All(x => x.Status == PartStatus.Processed); if (!isComplete) { var downloadedCount = part.ParentItem.Parts.Count(x => x.Status == PartStatus.Processed); var count = part.ParentItem.Parts.Count; progress = (double)downloadedCount / count; } else { _items.Remove(part.ParentItem); } } if (!isCanceled) { if (isComplete) { byte[] bytes = { }; foreach (var p in part.ParentItem.Parts) { var partBytes = p.File.Bytes; var redirect = part.ParentItem.CdnRedirect; if (redirect != null) { var iv = redirect.EncryptionIV; var counter = p.Offset / 16; iv[15] = (byte)(counter & 0xFF); iv[14] = (byte)((counter >> 8) & 0xFF); iv[13] = (byte)((counter >> 16) & 0xFF); iv[12] = (byte)((counter >> 24) & 0xFF); var key = CryptographicBuffer.CreateFromByteArray(redirect.EncryptionKey); var ecount_buf = new byte[0]; var num = 0u; partBytes = Utils.AES_ctr128_encrypt(partBytes, key, ref iv, ref ecount_buf, ref num); redirect.EncryptionIV = iv; //TLCdnFileHash hash; //if (!part.ParentItem.CdnHashes.TryGetValue(p.Offset, out hash)) //{ // var hashes = GetCdnFileHashes(redirect, part.ParentItem.Location, p.Offset, out TLRPCError er, out bool yolo); // if (hashes != null) // { // foreach (var item in hashes) // { // part.ParentItem.CdnHashes[item.Offset] = item; // } // part.ParentItem.CdnHashes.TryGetValue(p.Offset, out hash); // } //} //if (hash != null) //{ // var sha256 = Utils.ComputeSHA256(partBytes); // if (!sha256.SequenceEqual(hash.Hash)) // { // lock (_itemsSyncRoot) // { // part.ParentItem.IsCancelled = true; // part.Status = PartStatus.Processed; // _items.Remove(part.ParentItem); // } // Debug.WriteLine("HASH DOESN'T MATCH"); // return; // } //} } bytes = TLUtils.Combine(bytes, partBytes); } //part.ParentItem.Location.Buffer = bytes; var fileName = String.Format("{0}_{1}_{2}.jpg", part.ParentItem.Location.VolumeId, part.ParentItem.Location.LocalId, part.ParentItem.Location.Secret); FileUtils.WriteTemporaryBites(fileName, bytes); if (part.ParentItem.Callback != null) { part.ParentItem.Progress.Report(1.0); part.ParentItem.Callback.TrySetResult(part.ParentItem); } else { part.ParentItem.Action?.Invoke(part.ParentItem); Execute.BeginOnThreadPool(() => _eventAggregator.Publish(part.ParentItem)); } _statsService.IncrementReceivedItemsCount(_protoService.NetworkType, _dataType, 1); } else { if (part.ParentItem.Callback != null) { part.ParentItem.Progress.Report(progress); } else { Execute.BeginOnThreadPool(() => _eventAggregator.Publish(new DownloadProgressChangedEventArgs(part.ParentItem, progress))); } } } }
protected TLFileBase GetCdnFile(TLFileCdnRedirect redirect, TLInt offset, TLInt limit, out TLCdnFileReuploadNeeded reuploadNeeded, out TLRPCError er, out bool isCanceled, out bool isTokenInvalid) { var manualResetEvent = new ManualResetEvent(false); TLFileBase result = null; TLCdnFileReuploadNeeded outReuploadNeeded = null; TLRPCError outError = null; var outIsCanceled = false; var outIsTokenInvalid = false; _mtProtoService.GetCdnFileAsync(redirect.DCId, redirect.FileToken, offset, limit, cdnFileBase => { var cdnFile = cdnFileBase as TLCdnFile; if (cdnFile != null) { var iv = GetIV(redirect.EncryptionIV.Data, offset); var counter = offset.Value / 16; iv[15] = (byte)(counter & 0xFF); iv[14] = (byte)((counter >> 8) & 0xFF); iv[13] = (byte)((counter >> 16) & 0xFF); iv[12] = (byte)((counter >> 24) & 0xFF); var key = redirect.EncryptionKey.Data; var ecount_buf = new byte[0]; var num = 0u; var bytes = Utils.AES_ctr128_encrypt(cdnFile.Bytes.Data, key, ref iv, ref ecount_buf, ref num); result = new TLFile { Bytes = TLString.FromBigEndianData(bytes) }; } var cdnFileReuploadNeeded = cdnFileBase as TLCdnFileReuploadNeeded; if (cdnFileReuploadNeeded != null) { outReuploadNeeded = cdnFileReuploadNeeded; } manualResetEvent.Set(); }, error => { outError = error; if (error.CodeEquals(ErrorCode.INTERNAL) || (error.CodeEquals(ErrorCode.BAD_REQUEST) && (error.TypeEquals(ErrorType.LOCATION_INVALID) || error.TypeEquals(ErrorType.VOLUME_LOC_NOT_FOUND))) || (error.CodeEquals(ErrorCode.NOT_FOUND) && error.Message != null && error.Message.ToString().StartsWith("Incorrect dhGen"))) { outIsCanceled = true; manualResetEvent.Set(); return; } if (error.CodeEquals(ErrorCode.BAD_REQUEST) && error.TypeEquals(ErrorType.FILE_TOKEN_INVALID)) { outIsTokenInvalid = true; manualResetEvent.Set(); return; } int delay; lock (_randomRoot) { delay = _random.Next(1000, 3000); } Execute.BeginOnThreadPool(TimeSpan.FromMilliseconds(delay), () => manualResetEvent.Set()); }); manualResetEvent.WaitOne(); reuploadNeeded = outReuploadNeeded; er = outError; isCanceled = outIsCanceled; isTokenInvalid = outIsTokenInvalid; return(result); }