Using latest JNUSLib version

This commit is contained in:
Maschell 2019-04-26 20:26:49 +02:00
parent b5ee061a3a
commit 72a43e2820
3 changed files with 26 additions and 33 deletions

View File

@ -11,7 +11,7 @@ JNUSLib Decryptor 0.1 - Maschell
usage: usage:
-commonkey <WiiU common key> Optional. HexString. Will be used if no "common.key" in the folder -commonkey <WiiU common key> Optional. HexString. Will be used if no "common.key" in the folder
of this .jar is found of this .jar or in "~/.wiiu/common.key" is found
-file <regular expression> Decrypts the files that matches the given regular expression. -file <regular expression> Decrypts the files that matches the given regular expression.
-help shows this text -help shows this text
-in <input file> Input file. Expects a folder which contains the .app, and .tmd -in <input file> Input file. Expects a folder which contains the .app, and .tmd
@ -20,7 +20,6 @@ usage:
-overwrite Optional. Overwrites existing files -overwrite Optional. Overwrites existing files
-titlekey <Ticket title key> Optional. HexString. Will be used if no "title.tik" in the folder is -titlekey <Ticket title key> Optional. HexString. Will be used if no "title.tik" in the folder is
found found
-whole Decrypts the whole content files.
``` ```
Requires Java 8. Requires Java 8.

View File

@ -82,7 +82,7 @@
<dependency> <dependency>
<groupId>com.github.Maschell</groupId> <groupId>com.github.Maschell</groupId>
<artifactId>JNUSLib</artifactId> <artifactId>JNUSLib</artifactId>
<version> 6d98a8b </version> <version> 3eb299d </version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->

View File

@ -20,6 +20,7 @@ package de.mas.jnuslib.decryptor;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Optional;
import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.CommandLineParser;
@ -36,6 +37,7 @@ import de.mas.wiiu.jnus.NUSTitleLoaderLocal;
import de.mas.wiiu.jnus.Settings; import de.mas.wiiu.jnus.Settings;
import de.mas.wiiu.jnus.entities.TMD; import de.mas.wiiu.jnus.entities.TMD;
import de.mas.wiiu.jnus.entities.Ticket; import de.mas.wiiu.jnus.entities.Ticket;
import de.mas.wiiu.jnus.implementations.FSTDataProviderNUSTitle;
import de.mas.wiiu.jnus.utils.Utils; import de.mas.wiiu.jnus.utils.Utils;
public class Main { public class Main {
@ -45,8 +47,10 @@ public class Main {
private static final String OPTION_COMMON_KEY = "commonkey"; private static final String OPTION_COMMON_KEY = "commonkey";
private static final String OPTION_TITLEKEY = "titlekey"; private static final String OPTION_TITLEKEY = "titlekey";
private static final String OPTION_OVERWRITE = "overwrite"; private static final String OPTION_OVERWRITE = "overwrite";
private static final String OPTION_DECRYPT_WHOLE = "whole";
private static final String OPTION_FILE = "file"; private static final String OPTION_FILE = "file";
private static byte[] commonKey;
private static final String HOMEPATH = System.getProperty("user.home") + File.separator + ".wiiu";
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
System.out.println("JNUSLib Decryptor 0.1 - Maschell"); System.out.println("JNUSLib Decryptor 0.1 - Maschell");
@ -75,7 +79,9 @@ public class Main {
String output = null; String output = null;
boolean overwrite = false; boolean overwrite = false;
byte[] titlekey = null; byte[] titlekey = null;
readKey();
readKey(new File(HOMEPATH + File.separator + "common.key")).ifPresent(key -> Main.commonKey = key);
readKey(new File("common.key")).ifPresent(key -> Main.commonKey = key);
if (cmd.hasOption(OPTION_HELP)) { if (cmd.hasOption(OPTION_HELP)) {
showHelp(options); showHelp(options);
@ -93,7 +99,7 @@ public class Main {
String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY); String commonKey = cmd.getOptionValue(OPTION_COMMON_KEY);
byte[] key = Utils.StringToByteArray(commonKey); byte[] key = Utils.StringToByteArray(commonKey);
if (key.length == 0x10) { if (key.length == 0x10) {
Settings.commonKey = key; Main.commonKey = key;
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key)); System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key));
} }
} }
@ -118,21 +124,15 @@ public class Main {
} }
String regex = ".*"; String regex = ".*";
if (cmd.hasOption(OPTION_DECRYPT_WHOLE)) {
decryptContents(input, output, overwrite, titlekey);
return;
}
if (cmd.hasOption(OPTION_FILE)) { if (cmd.hasOption(OPTION_FILE)) {
regex = cmd.getOptionValue(OPTION_FILE); regex = cmd.getOptionValue(OPTION_FILE);
System.out.println("Decrypting files matching \"" + regex + "\""); System.out.println("Decrypting files matching \"" + regex + "\"");
} }
decryptFile(input, output, regex, overwrite, titlekey); decryptFile(input, output, regex, overwrite, titlekey);
} }
private static NUSTitle getTitle(String input, boolean overwrite, byte[] titlekey) throws IOException, Exception { private static NUSTitle getTitle(String input, boolean overwrite, byte[] titlekey) throws IOException, Exception {
if (input == null) { if (input == null) {
System.out.println("You need to provide an input file"); System.out.println("You need to provide an input file");
} }
@ -143,24 +143,15 @@ public class Main {
NUSTitle title = null; NUSTitle title = null;
if (titlekey != null) { if (titlekey != null) {
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(), title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(), Ticket.createTicket(titlekey,
Ticket.createTicket(titlekey, TMD.parseTMD(new File(inputFile.getAbsolutePath() + File.separator + Settings.TMD_FILENAME)).getTitleID())); TMD.parseTMD(new File(inputFile.getAbsolutePath() + File.separator + Settings.TMD_FILENAME)).getTitleID(), Main.commonKey));
} else { } else {
title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath()); title = NUSTitleLoaderLocal.loadNUSTitle(inputFile.getAbsolutePath(), Main.commonKey);
} }
return title; return title;
} }
private static void decryptContents(String input, String output, boolean overwrite, byte[] titleKey) throws IOException, Exception {
NUSTitle title = getTitle(input, overwrite, titleKey);
if (title == null) {
System.err.println("Failed to open title.");
return;
}
DecryptionService.getInstance(title).decryptAllPlainContents(output);
}
private static void decryptFile(String input, String output, String regex, boolean overwrite, byte[] titlekey) throws Exception { private static void decryptFile(String input, String output, String regex, boolean overwrite, byte[] titlekey) throws Exception {
NUSTitle title = getTitle(input, overwrite, titlekey); NUSTitle title = getTitle(input, overwrite, titlekey);
@ -180,21 +171,25 @@ public class Main {
File outputFolder = new File(newOutput); File outputFolder = new File(newOutput);
System.out.println("To the folder: " + outputFolder.getAbsolutePath()); System.out.println("To the folder: " + outputFolder.getAbsolutePath());
title.setSkipExistingFiles(!overwrite); DecryptionService decryption = DecryptionService.getInstance(new FSTDataProviderNUSTitle(title));
DecryptionService decryption = DecryptionService.getInstance(title);
decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath()); decryption.decryptFSTEntriesTo(regex, outputFolder.getAbsolutePath(), overwrite);
System.out.println("Decryption done"); System.out.println("Decryption done");
} }
private static void readKey() throws IOException { private static Optional<byte[]> readKey(File file) {
File file = new File("common.key");
if (file.isFile()) { if (file.isFile()) {
byte[] key = Files.readAllBytes(file.toPath()); byte[] key;
Settings.commonKey = key; try {
System.out.println("Commonkey was set to: " + Utils.ByteArrayToString(key)); key = Files.readAllBytes(file.toPath());
if (key != null && key.length == 16) {
return Optional.of(key);
} }
} catch (IOException e) {
}
}
return Optional.empty();
} }
private static Options getOptions() { private static Options getOptions() {
@ -210,7 +205,6 @@ public class Main {
.desc("Optional. HexString. Will be used if no \"title.tik\" in the folder is found").build()); .desc("Optional. HexString. Will be used if no \"title.tik\" in the folder is found").build());
options.addOption(Option.builder(OPTION_FILE).argName("regular expression").hasArg() options.addOption(Option.builder(OPTION_FILE).argName("regular expression").hasArg()
.desc("Decrypts the files that matches the given regular expression.").build()); .desc("Decrypts the files that matches the given regular expression.").build());
options.addOption(Option.builder(OPTION_DECRYPT_WHOLE).desc("Decrypts the whole content files.").build());
options.addOption(OPTION_HELP, false, "shows this text"); options.addOption(OPTION_HELP, false, "shows this text");