private static void Main(string[] args) { // Check if enough args were passed if (args.Length != 2) { Console.WriteLine("NisasystSharp <game path> <file path>" + "\nExample: NisasystSharp Mush/ActorDb.release.byml C:\\Blitz\\ActorDb.Release.byml"); return; } using (var file = File.OpenRead(args[1])) using (var reader = new BinaryReader(file)) { // Length of the file, minus the "nisasyst" magic var len = (int)file.Length - 8; // Seek to the magic numbers file.Position = len; // Verify the magic numbers if (reader.ReadUInt64() != 0x747379736173696e) { // This isn't a valid file Console.WriteLine("This file isn't a nisasyst container"); return; } // Move back to the beginning of the file file.Position = 0; // Create a CRC32 over the game path, and a new SeadRandom instance using the seed var seadRandom = new SeadRand(Crc32(args[0])); // Create the encryption key and IV byte[] key = CreateSequence(seadRandom), iv = CreateSequence(seadRandom); using (var ms = new MemoryStream()) using (var aes = new AesCryptoServiceProvider() { Mode = CipherMode.CBC, Padding = PaddingMode.PKCS7 }) { using (var crypt = aes.CreateDecryptor(key, iv)) File.WriteAllBytes($"{args[1]}.decrypted", crypt.TransformFinalBlock(reader.ReadBytes(len), 0, len)); Console.WriteLine("Wrote decrypted file"); } } }
private static byte[] CreateSequence(SeadRand random) { // Create byte array var sequence = new byte[16]; // Create each byte for (int i = 0; i < sequence.Length; i++) { // Create empty byte string var byteString = string.Empty; // Get characters from key material byteString += KeyMaterial[random.GetU32() >> 24]; byteString += KeyMaterial[random.GetU32() >> 24]; // Parse the resulting byte sequence[i] = Convert.ToByte(byteString, 16); } // Return the sequence return(sequence); }