예제 #1
0
        /// <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;
        }
예제 #2
0
            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();
            }