private static async Task <(MemoryStream output, IMS2SizeHeader size)> InternalGetEncryptionStreamAsync(Stream input, long inputSize, IBufferedCipher cipher, long headerSize) { byte[] inputBytes = new byte[inputSize]; int read = await input.ReadAsync(inputBytes, 0, (int)inputSize).ConfigureAwait(false); if (inputSize != read) { throw new EndOfStreamException(); } using var msInput = new MemoryStream(inputBytes); using var cs = new CipherStream(msInput, cipher, null); using var ms = new MemoryStream(); var output = new MemoryStream(); await cs.CopyToAsync(ms).ConfigureAwait(false); var data = ms.ToArray(); var encoder = new Base64Encoder(); encoder.Encode(data, 0, data.Length, output); var header = new MS2SizeHeader(output.Length, inputSize, headerSize); output.Position = 0; return(output, header); }
private static Task <MS2Archive> LoadMS2F(MS2CryptoMode cryptoMode, BinaryReader br, string name, MemoryMappedFile dataMemoryMappedFile) { return(Task.Run(async() => { uint unk = br.ReadUInt32(); // TODO: unknown/unused? uint dataCompressedSize = br.ReadUInt32() | br.ReadUInt32(); uint dataEncodedSize = br.ReadUInt32() | br.ReadUInt32(); uint size = br.ReadUInt32() | br.ReadUInt32(); uint compressedSize = br.ReadUInt32() | br.ReadUInt32(); uint encodedSize = br.ReadUInt32() | br.ReadUInt32(); uint fileCount = br.ReadUInt32() | br.ReadUInt32(); uint dataSize = br.ReadUInt32() | br.ReadUInt32(); if (unk != 0) { Logger.Debug($"Archive header unk is \"{unk}\"."); } var header = new MS2SizeHeader(encodedSize, compressedSize, size); var data = new MS2SizeHeader(dataEncodedSize, dataCompressedSize, dataSize); Logger.Verbose($"There are {fileCount} files in the archive."); List <MS2File> files = await LoadFiles(cryptoMode, header, data, fileCount, br, dataMemoryMappedFile).ConfigureAwait(false); var archive = new MS2Archive(cryptoMode, header, data, name, dataMemoryMappedFile, files); return archive; })); }
private MS2Archive(MS2CryptoMode cryptoMode, MS2SizeHeader header, MS2SizeHeader data, string name, MemoryMappedFile dataFile, List <MS2File> files) { this.Name = name; this.DataFile = dataFile; this.CryptoMode = cryptoMode; this.Header = header; this.Data = data; this.Files = files; }
public static async Task <(byte[] Bytes, MS2SizeHeader Header)> EncryptDataToDataAsync(MS2CryptoMode cryptoMode, bool compress, byte[] bytes) { if (compress) { byte[] compressedBytes = await Task.Run(() => Compress(bytes)).ConfigureAwait(false); byte[] encryptedBytes = await Task.Run(() => EncryptNoCompress(cryptoMode, compressedBytes, (uint)compressedBytes.Length)).ConfigureAwait(false); var header = new MS2SizeHeader((uint)encryptedBytes.Length, (uint)compressedBytes.Length, (uint)bytes.Length); return(encryptedBytes, header); } else { byte[] encryptedBytes = await Task.Run(() => EncryptNoCompress(cryptoMode, bytes, (uint)bytes.Length)).ConfigureAwait(false); var header = new MS2SizeHeader((uint)encryptedBytes.Length, (uint)bytes.Length, (uint)bytes.Length); return(encryptedBytes, header); } }
private static Task <MS2Archive> LoadNS2F(MS2CryptoMode cryptoMode, BinaryReader br, string name, MemoryMappedFile dataMemoryMappedFile) { return(Task.Run(async() => { uint fileCount = br.ReadUInt32(); uint dataCompressedSize = br.ReadUInt32() | br.ReadUInt32(); uint dataEncodedSize = br.ReadUInt32() | br.ReadUInt32(); uint size = br.ReadUInt32() | br.ReadUInt32(); uint compressedSize = br.ReadUInt32() | br.ReadUInt32(); uint encodedSize = br.ReadUInt32() | br.ReadUInt32(); uint dataSize = br.ReadUInt32() | br.ReadUInt32(); var header = new MS2SizeHeader(encodedSize, compressedSize, size); var data = new MS2SizeHeader(dataEncodedSize, dataCompressedSize, dataSize); List <MS2File> files = await LoadFiles(cryptoMode, header, data, fileCount, br, dataMemoryMappedFile).ConfigureAwait(false); var archive = new MS2Archive(cryptoMode, header, data, name, dataMemoryMappedFile, files); return archive; })); }
public static Task <Stream> DecryptStreamToStreamAsync(MS2CryptoMode cryptoMode, MS2SizeHeader header, bool isCompressed, Stream stream) { return(DecryptStreamToDataAsync(cryptoMode, header, isCompressed, stream).ContinueWith <Stream>(t => new MemoryStream(t.Result))); }
public static async Task <byte[]> DecryptDataToDataAsync(MS2CryptoMode cryptoMode, MS2SizeHeader header, bool isCompressed, byte[] bytes) { if (header.EncodedSize == 0 || header.CompressedSize == 0 || header.Size == 0) { return(new byte[0]); } if (isCompressed) { return(await Task.Run(() => Decrypt(cryptoMode, bytes, header.CompressedSize, header.Size)).ConfigureAwait(false)); } else { return(await Task.Run(() => DecryptNoDecompress(cryptoMode, bytes, header.Size)).ConfigureAwait(false)); } }
public static async Task <byte[]> DecryptStreamToDataAsync(MS2CryptoMode cryptoMode, MS2SizeHeader header, bool isCompressed, Stream stream) { if (header.EncodedSize == 0 || header.CompressedSize == 0 || header.Size == 0) { return(new byte[0]); } byte[] buffer = new byte[header.EncodedSize]; uint readBytes = (uint)await stream.ReadAsync(buffer, 0, (int)header.EncodedSize).ConfigureAwait(false); if (readBytes != header.EncodedSize) { throw new Exception("Data length mismatch when reading data."); } return(await DecryptDataToDataAsync(cryptoMode, header, isCompressed, buffer).ConfigureAwait(false)); }
internal static MS2FileHeader Create(uint id, uint offset, CompressionType compressionType, MS2SizeHeader header) => new MS2FileHeader(header.EncodedSize, header.CompressedSize, header.Size, id, offset, compressionType);
private static async Task <List <MS2File> > LoadFiles(MS2CryptoMode cryptoMode, MS2SizeHeader header, MS2SizeHeader data, uint fileCount, BinaryReader br, MemoryMappedFile dataMemoryMappedFile) { var files = new List <MS2File>((int)fileCount); // TODO: are those always compressed? using (Stream headerStream = await DecryptStreamToStreamAsync(cryptoMode, header, true, br.BaseStream).ConfigureAwait(false)) using (Stream dataStream = await DecryptStreamToStreamAsync(cryptoMode, data, true, br.BaseStream).ConfigureAwait(false)) { for (int i = 0; i < fileCount; i++) { files.Add(await MS2File.Load(cryptoMode, headerStream, dataStream, dataMemoryMappedFile).ConfigureAwait(false)); } return(files); } }