Пример #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 (IsProcessed)
                {
                    return;
                }

                byte[] processedData = CryptoHelper.SymmetricDecrypt(Data, depotKey);
                processedData = ZipUtil.Decompress(processedData);

                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
        /// <summary>
        /// Begins a request to upload a file to the UFS.
        /// The <see cref="UFSClient"/> should be logged on before this point.
        /// Results are returned in a <see cref="UploadFileResponseCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for uploading the file.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="UploadFileResponseCallback"/>.</returns>
        public JobID RequestFileUpload(UploadDetails details)
        {
            byte[] compressedData = ZipUtil.Compress(details.FileData);

            var msg = new ClientMsgProtobuf <CMsgClientUFSUploadFileRequest>(EMsg.ClientUFSUploadFileRequest);

            msg.SourceJobID = steamClient.GetNextJobID();

            msg.Body.app_id        = details.AppID;
            msg.Body.can_encrypt   = false;
            msg.Body.file_name     = details.FileName;
            msg.Body.file_size     = ( uint )compressedData.Length;
            msg.Body.raw_file_size = ( uint )details.FileData.Length;
            msg.Body.sha_file      = CryptoHelper.SHAHash(details.FileData);
            msg.Body.time_stamp    = DateUtils.DateTimeToUnixTime(DateTime.UtcNow);

            Send(msg);

            return(msg.SourceJobID);
        }
Пример #3
0
        /// <summary>
        /// Downloads the depot manifest specified by the given manifest ID, and optionally decrypts the manifest's filenames if the depot decryption key has been provided.
        /// </summary>
        /// <param name="depotId">The id of the depot being accessed.</param>
        /// <param name="manifestId">The unique identifier of the manifest to be downloaded.</param>
        /// <param name="server">The content server to connect to.</param>
        /// <param name="cdnAuthToken">CDN auth token for CDN content server endpoints.</param>
        /// <param name="depotKey">
        /// The depot decryption key for the depot that will be downloaded.
        /// This is used for decrypting filenames (if needed) in depot manifests, and processing depot chunks.
        /// </param>
        /// <param name="proxyServer">Optional content server marked as UseAsProxy which transforms the request.</param>
        /// <returns>A <see cref="DepotManifest"/> instance that contains information about the files present within a depot.</returns>
        /// <exception cref="System.ArgumentNullException"><see ref="server"/> was null.</exception>
        /// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception>
        /// <exception cref="SteamKitWebRequestException">A network error occurred when performing the request.</exception>
        public async Task <DepotManifest> DownloadManifestAsync(uint depotId, ulong manifestId, Server server, string?cdnAuthToken, byte[]?depotKey, Server?proxyServer = null)
        {
            if (server == null)
            {
                throw new ArgumentNullException(nameof(server));
            }

            var manifestData = await DoRawCommandAsync(server, string.Format("depot/{0}/manifest/{1}/5", depotId, manifestId), cdnAuthToken, proxyServer).ConfigureAwait(false);

            manifestData = ZipUtil.Decompress(manifestData);

            var depotManifest = new DepotManifest(manifestData);

            if (depotKey != null)
            {
                // if we have the depot key, decrypt the manifest filenames
                depotManifest.DecryptFilenames(depotKey);
            }

            return(depotManifest);
        }
Пример #4
0
        /// <summary>
        /// Downloads the depot manifest specified by the given manifest ID, and optionally decrypts the manifest's filenames if the depot decryption key has been provided.
        /// </summary>
        /// <param name="depotId">The id of the depot being accessed.</param>
        /// <param name="manifestId">The unique identifier of the manifest to be downloaded.</param>
        /// <returns>A <see cref="DepotManifest"/> instance that contains information about the files present within a depot.</returns>
        public DepotManifest DownloadManifest(uint depotId, ulong manifestId)
        {
            string cdnToken = null;

            depotCdnAuthKeys.TryGetValue(depotId, out cdnToken);

            byte[] compressedManifest = DoRawCommand(connectedServer, "depot", doAuth: true, args: string.Format("{0}/manifest/{1}/5", depotId, manifestId), authtoken: cdnToken);

            byte[] manifestData = ZipUtil.Decompress(compressedManifest);

            var depotManifest = new DepotManifest(manifestData);

            byte[] depotKey;
            if (depotKeys.TryGetValue(depotId, out depotKey))
            {
                // if we have the depot key, decrypt the manifest filenames
                depotManifest.DecryptFilenames(depotKey);
            }

            return(depotManifest);
        }
Пример #5
0
        /// <summary>
        /// Uploads the actual contents of a file to the UFS.
        /// The <see cref="UFSClient"/> should be logged on before this point, and the previous request to upload a file must have completed successfully.
        /// Results are returned in a <see cref="UploadFileFinishedCallback"/>.
        /// </summary>
        /// <param name="details">The details to use for uploading the file.</param>
        /// <returns>The Job ID of the request. This can be used to find the appropriate <see cref="UploadFileFinishedCallback"/>.</returns>
        public void UploadFile(UploadDetails details)
        {
            if (details == null)
            {
                throw new ArgumentNullException(nameof(details));
            }

            const uint MaxBytesPerChunk = 10240;

            byte[] compressedData = ZipUtil.Compress(details.FileData);
            byte[] fileHash       = CryptoHelper.SHAHash(details.FileData);

            var buffer = new byte[MaxBytesPerChunk];

            using (var ms = new MemoryStream(compressedData))
            {
                for (long readIndex = 0; readIndex < ms.Length; readIndex += buffer.Length)
                {
                    var msg = new ClientMsgProtobuf <CMsgClientUFSFileChunk>(EMsg.ClientUFSUploadFileChunk);
                    msg.TargetJobID = details.RemoteJobID;

                    var bytesRead = ms.Read(buffer, 0, buffer.Length);

                    if (bytesRead < buffer.Length)
                    {
                        msg.Body.data = buffer.Take(bytesRead).ToArray();
                    }
                    else
                    {
                        msg.Body.data = buffer;
                    }

                    msg.Body.file_start = ( uint )readIndex;
                    msg.Body.sha_file   = fileHash;

                    Send(msg);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Downloads the depot manifest specified by the given manifest ID, and optionally decrypts the manifest's filenames if the depot decryption key has been provided.
        /// </summary>
        /// <param name="depotId">The id of the depot being accessed.</param>
        /// <param name="manifestId">The unique identifier of the manifest to be downloaded.</param>
        /// <param name="host">CDN hostname.</param>
        /// <param name="cdnAuthToken">CDN auth token for CDN content server endpoints.</param>
        /// <param name="depotKey">
        /// The depot decryption key for the depot that will be downloaded.
        /// This is used for decrypting filenames (if needed) in depot manifests, and processing depot chunks.
        /// </param>
        /// <returns>A <see cref="DepotManifest"/> instance that contains information about the files present within a depot.</returns>
        public DepotManifest DownloadManifest(uint depotId, ulong manifestId, string host, string cdnAuthToken, byte[] depotKey = null)
        {
            var server = new Server
            {
                Host = host,
                Port = 80
            };

            byte[] manifestData = DoRawCommand(server, "depot", doAuth: true, args: string.Format("{0}/manifest/{1}/5", depotId, manifestId), authtoken: cdnAuthToken);

            manifestData = ZipUtil.Decompress(manifestData);

            var depotManifest = new DepotManifest(manifestData);

            if (depotKey != null)
            {
                // if we have the depot key, decrypt the manifest filenames
                depotManifest.DecryptFilenames(depotKey);
            }

            return(depotManifest);
        }
Пример #7
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;
                }

                if (Data != null)
                {
                    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);
                    }

                    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;
                }
                if (DataStream != null)
                {
                    Stream reProcessedData;
                    using (Stream processedData = CryptoHelper.SymmetricDecrypt(DataStream, depotKey))
                    {
                        int firstByte  = processedData.ReadByte();
                        int secondByte = processedData.ReadByte();
                        processedData.Position = 0;

                        if (firstByte == 86 && secondByte == 90)
                        {
                            reProcessedData = VZipUtil.Decompress(processedData);
                        }
                        else
                        {
                            reProcessedData = ZipUtil.Decompress(processedData);
                        }
                    }

                    byte[] dataCrc = CryptoHelper.AdlerHash(reProcessedData);

                    if (!dataCrc.SequenceEqual(ChunkInfo.Checksum))
                    {
                        throw new InvalidDataException("Processed data checksum is incorrect! Downloaded depot chunk is corrupt or invalid/wrong depot key?");
                    }

                    DataStream  = reProcessedData;
                    IsProcessed = true;
                }
            }