Last active
June 5, 2018 14:10
-
-
Save Thealexbarney/b3f39f546f80a6f5317478ebcf3d4a5d to your computer and use it in GitHub Desktop.
Pokemon Quest save decrypter and encrypter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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