/// <summary> /// For traditional decryption /// </summary> /// <param name="inStream"></param> /// <param name="outStream"></param> /// <param name="seed"></param> /// <param name="fileSize"></param> /// <param name="offset"></param> public void Decrypt(Stream inStream, Stream outStream, uint seed, ulong fileSize, ulong offset) { uint crc = ~CRC32.CRC32_0x04C11DB7(_keys.Magic, 0); uint[] keys = PrepareKey(crc ^ seed, _keys.Key.Data); byte[] table = GenerateBitsTable(keys); byte[] buffer = ArrayPool <byte> .Shared.Rent(0x20000); while (fileSize > 0) { ulong bufferSize = fileSize; if (fileSize > 0x20000) { bufferSize = 0x20000; } inStream.Position = (long)offset; inStream.Read(buffer); DecryptBuffer(buffer, buffer, (int)bufferSize, table, offset); outStream.Write(buffer.AsSpan(0, (int)bufferSize)); fileSize -= bufferSize; offset += bufferSize; } ArrayPool <byte> .Shared.Return(buffer); }
/// <summary> /// Key computing GT5P JP Demo /// </summary> /// <param name="seed"></param> /// <returns></returns> private uint[] PrepareKeyOld(uint seed) { var keysetSeedCrc = ~CRC32.CRC32_0x04C11DB7(_keys.Magic, 0); uint one = CRC32.CRC32UInt(seed ^ keysetSeedCrc); uint two = CRC32.CRC32UInt(one); uint three = CRC32.CRC32UInt(two); uint four = CRC32.CRC32UInt(three); uint[] keys = new uint[4]; keys[0] = one & 0x1FFFF; keys[1] = two & 0x7ffff; keys[2] = three & 0x7fffff; keys[3] = four & 0x1fffffff; return(keys); }