Last active
June 5, 2018 14:10
Star
You must be signed in to star a gist
Pokemon Quest save decrypter and encrypter
This file contains 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