/// <summary> /// Processes the specified depot key by decrypting the data with the given depot encryption key, and then by decompressing the data. /// If the chunk has already been processed, this function does nothing. /// </summary> /// <param name="depotKey">The depot decryption key.</param> /// <exception cref="System.IO.InvalidDataException">Thrown if the processed data does not match the expected checksum given in it's chunk information.</exception> public void Process(byte[] depotKey) { if (depotKey == null) { throw new ArgumentNullException(nameof(depotKey)); } if (IsProcessed) { return; } byte[] processedData = CryptoHelper.SymmetricDecrypt(Data, depotKey); if (processedData.Length > 1 && processedData[0] == 'V' && processedData[1] == 'Z') { processedData = VZipUtil.Decompress(processedData); } else { processedData = ZipUtil.Decompress(processedData); } DebugLog.Assert(ChunkInfo.Checksum != null, nameof(DepotChunk), "Expected data chunk to have a checksum."); byte[] dataCrc = CryptoHelper.AdlerHash(processedData); if (!dataCrc.SequenceEqual(ChunkInfo.Checksum)) { throw new InvalidDataException("Processed data checksum is incorrect! Downloaded depot chunk is corrupt or invalid/wrong depot key?"); } Data = processedData; IsProcessed = true; }
public void Work() { Task = Task.Factory.StartNew(async() => { while (!_stop || !_filesHandler._downloadedChunksBuffer.IsEmpty) { if (_filesHandler._downloadedChunksBuffer.IsEmpty) { await Task.Delay(100); } bool hasData = _filesHandler._downloadedChunksBuffer.TryDequeue(out (ChunkTask chunkTask, byte[] data)availableData); if (!hasData) { continue; } try { var depotChunk = new SteamKit2.CDNClient.DepotChunk(availableData.chunkTask.InternalChunk, availableData.data); var verified = false; if (_filesHandler._depotKey != null) { depotChunk.Process(_filesHandler._depotKey); verified = true; } if (!verified) { using (SHA1Managed sha1 = new SHA1Managed()) { if (!depotChunk.ChunkInfo.Checksum.SequenceEqual(CryptoHelper.AdlerHash(depotChunk.Data))) { throw new InvalidOperationException("Invalid chunk data received."); } } } await availableData.chunkTask.FileWriter.WriteAsync(availableData.chunkTask.Chunk.Offset, depotChunk.Data); } catch (InvalidOperationException) { _filesHandler._chunks.Enqueue(availableData.chunkTask); } catch (Exception ex) { throw new SteamDownloadTaskFileTargetWrappedException(availableData.chunkTask.FileWriter.Target, ex); } } }, TaskCreationOptions.LongRunning).GetAwaiter().GetResult(); }