Skip to content

Instantly share code, notes, and snippets.

@Thealexbarney
Last active June 5, 2018 14:10
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Thealexbarney/b3f39f546f80a6f5317478ebcf3d4a5d to your computer and use it in GitHub Desktop.
Pokemon Quest save decrypter and encrypter
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace PqCrypt
{
public static class Program
{
public static readonly byte[] Key = Encoding.UTF8.GetBytes("C7PxX4jPfPQ2SmzB");
public static readonly byte[] Iv = Encoding.UTF8.GetBytes("nSdhdc3ecDDEM7fA");
public static readonly byte[] ChecksumKey = Encoding.UTF8.GetBytes("chikuwa-hanpen");
public static readonly int SaveLength = 0x80000;
static void Main(string[] args)
{
if (args.Length != 3)
{
PrintUsage();
return;
}
switch (args[0])
{
case "d":
var encSave = File.ReadAllBytes(args[1]);
File.WriteAllBytes(args[2], DecryptSave(encSave));
break;
case "e":
var decSave = File.ReadAllBytes(args[1]);
File.WriteAllBytes(args[2], EncryptSave(decSave));
break;
default:
PrintUsage();
return;
}
}
private static void PrintUsage()
{
Console.WriteLine("Usage: pqdecrypt d <enc_save_in> <dec_save_out>");
Console.WriteLine(" pqdecrypt e <dec_save_in> <enc_save_out>");
}
private static byte[] EncryptSave(byte[] save)
{
// Recalculate hash
var hash = new HMACSHA256(ChecksumKey);
var checksum = hash.ComputeHash(save, 0x38, save.Length - 0x38);
Array.Copy(checksum, 0, save, 0x14, 0x20);
// Encrypt head and body chunks
var encryptedLength = save.Length + 16 & ~0xF;
var head = Encrypt(BitConverter.GetBytes(encryptedLength), 0, 4);
var body = Encrypt(save, 0, save.Length);
// Concat the 2 chunks
var encrypted = new byte[SaveLength];
Array.Copy(head, encrypted, 16);
Array.Copy(body, 0, encrypted, 16, body.Length);
return encrypted;
}
private static byte[] DecryptSave(byte[] saveEnc)
{
var length = BitConverter.ToInt32(Decrypt(saveEnc, 0, 16), 0);
return Decrypt(saveEnc, 16, length);
}
private static byte[] Encrypt(byte[] data, int index, int length)
{
using (var aes = Aes.Create())
using (var encryptor = aes.CreateEncryptor(Key, Iv))
return Transform(data, index, length, encryptor);
}
private static byte[] Decrypt(byte[] data, int index, int length)
{
using (var aes = Aes.Create())
using (var decryptor = aes.CreateDecryptor(Key, Iv))
return Transform(data, index, length, decryptor);
}
private static byte[] Transform(byte[] data, int index, int length, ICryptoTransform decryptor)
{
using (var ms = new MemoryStream())
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
{
cs.Write(data, index, length);
cs.FlushFinalBlock();
return ms.ToArray();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment