Beispiel #1
0
        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);
        }
Beispiel #2
0
        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;
            }));
        }
Beispiel #3
0
        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;
        }
Beispiel #4
0
        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);
            }
        }
Beispiel #5
0
        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;
            }));
        }
Beispiel #6
0
 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)));
 }
Beispiel #7
0
        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));
            }
        }
Beispiel #8
0
        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));
        }
Beispiel #9
0
 internal static MS2FileHeader Create(uint id, uint offset, CompressionType compressionType, MS2SizeHeader header)
 => new MS2FileHeader(header.EncodedSize, header.CompressedSize, header.Size, id, offset, compressionType);
Beispiel #10
0
        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);
                }
        }