Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pak6 encryption support #140

Draft
wants to merge 31 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e0e4d0c
pak18 tricks
AurisTFG Jan 13, 2025
26052a7
Merge branch 'BigBang1112:dev' into dev
AurisTFG Feb 1, 2025
a1fbff5
refactor extract folder path
AurisTFG Feb 1, 2025
7174197
fix Pak6 dataStart
AurisTFG Feb 3, 2025
401346e
add LZ4Stream
AurisTFG Feb 3, 2025
cc506bd
fix IsCompressed flag, add IsEncrypted
AurisTFG Feb 3, 2025
be680c6
Fix OpenFile for unecrypted files and add LZ4
AurisTFG Feb 3, 2025
a70f6af
implement reading keys from keys.txt
AurisTFG Feb 3, 2025
af53d24
Merge branch 'BigBang1112:dev' into dev
AurisTFG Feb 3, 2025
fae138e
make EncryptionInitializer nullable
AurisTFG Feb 3, 2025
38076c5
implement NonDisposingStream
AurisTFG Feb 3, 2025
8ebf578
fix file offset to be uint
AurisTFG Feb 3, 2025
81c95d1
search for titlepacks in directory
AurisTFG Feb 3, 2025
ed21dd2
try to save non encrypted gbx files
AurisTFG Feb 3, 2025
b9ab062
cleanup
AurisTFG Feb 3, 2025
93abb1e
support unencrypted headers
AurisTFG Feb 9, 2025
74e6b0c
refactor header reading functions
AurisTFG Feb 9, 2025
6b8d30c
support for pak6 file name bruteforce
AurisTFG Feb 14, 2025
baa5007
Merge branch 'BigBang1112:dev' into dev
AurisTFG Feb 14, 2025
857800f
Tweaks and patches
BigBang1112 Feb 22, 2025
d6b774b
Bring back game selection
BigBang1112 Feb 22, 2025
2e1670a
Fix other pak toolings
BigBang1112 Feb 22, 2025
9bc0e0e
Make PakKeyInfo nullable
BigBang1112 Feb 22, 2025
dde4332
More nullable
BigBang1112 Feb 22, 2025
4d0fc87
More nullable
BigBang1112 Feb 22, 2025
d8cff3b
Add version support for read/write
BigBang1112 Feb 22, 2025
1f1a3a5
Implement some MP4 classes
BigBang1112 Feb 22, 2025
dbf225a
Merge pull request #1 from AurisTFG/patches
AurisTFG Feb 23, 2025
f222b42
Implement CPlugFlockModel
BigBang1112 Feb 23, 2025
dbfaa8c
Bitmap, sound, zone fixes
BigBang1112 Feb 23, 2025
1e82b1c
Merge pull request #2 from AurisTFG/patches
AurisTFG Feb 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions Generators/GBX.NET.Generators/ChunkL/MemberSerializationWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,20 @@ private void AppendRead(int indent, ChunkProperty chunkProperty)

sb.AppendIndent(indent);

if (!self && !isUnknown)
if (chunkProperty.Type.PrimaryType is "version" or "versionb")
{
sb.Append("n.");
sb.Append("Version");
}
else
{
if (!self && !isUnknown)
{
sb.Append("n.");
}

sb.Append(name);
}

sb.Append(name);
sb.Append(" = ");

if (chunkProperty is ChunkEnum chunkEnum)
Expand All @@ -289,6 +297,18 @@ private void AppendRead(int indent, ChunkProperty chunkProperty)

sb.Append("r.Read");

if (chunkProperty.Type.PrimaryType == "version")
{
sb.Append("Int32();");
return;
}

if (chunkProperty.Type.PrimaryType == "versionb")
{
sb.Append("Byte();");
return;
}

if (chunkProperty.Type.IsArray)
{
sb.Append("Array");
Expand Down
69 changes: 66 additions & 3 deletions Src/GBX.NET.PAK/Blowfish.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ namespace GBX.NET.PAK;
/// </summary>
internal sealed class Blowfish
{
private const int N = 16;
private int N = 16;

private readonly uint[] P = [
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0,
Expand Down Expand Up @@ -226,7 +226,7 @@ internal sealed class Blowfish
/// Constructs and initializes a blowfish instance with the supplied key.
/// </summary>
/// <param name="key">The key to cipher with.</param>
public Blowfish(byte[] key)
public Blowfish(byte[] key, bool isPak18 = false)
{
short i;
short j;
Expand All @@ -235,6 +235,12 @@ public Blowfish(byte[] key)
uint datal;
uint datar;

// Trick #1: reduce N from 16 to 8
if (isPak18)
{
N = 8;
}

j = 0;
for (i = 0; i < N + 2; ++i)
{
Expand Down Expand Up @@ -271,6 +277,16 @@ public Blowfish(byte[] key)
S[i, j + 1] = datar;
}
}

// Trick #2: reverse the order of first 10 elements in the P array
if (isPak18)
{
uint[] temp = (uint[])P.Clone();
for (i = 0; i < 10; i++)
{
P[i] = temp[9 - i];
}
}
}

/// <summary>
Expand Down Expand Up @@ -300,6 +316,53 @@ private uint F(uint x)
return y;
}

/// <summary>
/// Encrypts a byte array in place.
/// </summary>
/// <param name="data">The array to encrypt.</param>
/// <param name="length">The amount to encrypt.</param>
public void Encipher(byte[] data)
{
if (data.Length % 8 != 0)
{
throw new Exception("Invalid Length");
}

for (int i = 0; i < data.Length; i += 8)
{
// Encode the data in 8 byte blocks.
var xl = BitConverter.ToUInt32(data, i);
var xr = BitConverter.ToUInt32(data, i + 4);
Encipher(ref xl, ref xr);
Array.Copy(BitConverter.GetBytes(xl), 0, data, i, 4);
Array.Copy(BitConverter.GetBytes(xr), 0, data, i + 4, 4);
}
}

#if NET5_0_OR_GREATER
/// <summary>
/// Encrypts a byte span in place.
/// </summary>
/// <param name="data">The array to encrypt.</param>
/// <param name="length">The amount to encrypt.</param>
public void Encipher(Span<byte> data)
{
if (data.Length % 8 != 0)
{
throw new Exception("Invalid Length");
}

for (int i = 0; i < data.Length; i += 8)
{
// Encode the data in 8 byte blocks.
var xl = BitConverter.ToUInt32(data.Slice(i));
var xr = BitConverter.ToUInt32(data.Slice(i + 4));
Encipher(ref xl, ref xr);
BitConverter.TryWriteBytes(data.Slice(i), xl);
BitConverter.TryWriteBytes(data.Slice(i + 4), xr);
}
}
#endif

/// <summary>
/// Encrypts 8 bytes of data (1 block)
Expand Down Expand Up @@ -393,7 +456,7 @@ private void Decipher(ref uint xl, ref uint xr)
uint Xl;
uint Xr;
uint temp;
short i;
int i;

Xl = xl;
Xr = xr;
Expand Down
41 changes: 36 additions & 5 deletions Src/GBX.NET.PAK/BlowfishStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ public class BlowfishStream : Stream, IEncryptionInitializer
#endif
private int bufferIndex;
private int totalIndex;
private bool isPak18;

public BlowfishStream(Stream stream, byte[] key, ulong iv)
public BlowfishStream(Stream stream, byte[] key, ulong iv, bool isPak18 = false)
{
this.stream = stream ?? throw new ArgumentNullException(nameof(BlowfishStream.stream));
blowfish = new Blowfish(key);
blowfish = new Blowfish(key, isPak18);
this.iv = iv;
memoryBuffer = new byte[8];
this.isPak18 = isPak18;
}

public override bool CanRead => stream.CanRead;
Expand Down Expand Up @@ -75,19 +77,48 @@ public override int Read(byte[] buffer, int offset, int count)
#if NET5_0_OR_GREATER
var read = stream.Read(memorySpan);
var nextIV = BitConverter.ToUInt64(memorySpan);
blowfish.Decipher(memorySpan);

// Trick #3: Switch Decipher with Encipher
if(isPak18)
{
blowfish.Encipher(memorySpan);
}
else
{
blowfish.Decipher(memorySpan);
}

var block = BitConverter.ToUInt64(memorySpan);
block ^= iv;
BitConverter.TryWriteBytes(memorySpan, block);
#else
var read = stream.Read(memoryBuffer, 0, 8);
ulong nextIV = BitConverter.ToUInt64(memoryBuffer, 0);
blowfish.Decipher(memoryBuffer);

// Trick #3: Switch Decipher with Encipher
if(isPak18)
{
blowfish.Encipher(memoryBuffer);
}
else
{
blowfish.Decipher(memoryBuffer);
}

ulong block = BitConverter.ToUInt64(memoryBuffer, 0);
block ^= iv;
memoryBuffer = BitConverter.GetBytes(block);
#endif
iv = nextIV;

// Trick #4: Custom nextIV logic
if (isPak18)
{
iv = iv >> 0x2f ^ iv * 9 ^ nextIV;
}
else
{
iv = nextIV;
}
}
#if NET5_0_OR_GREATER
buffer[offset + i] = memorySpan[bufferIndex % 8];
Expand Down
1 change: 1 addition & 0 deletions Src/GBX.NET.PAK/GBX.NET.PAK.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

<GenerateDocumentationFile>false</GenerateDocumentationFile>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
Expand Down
Loading
Loading