logo upd; TitleKEKs added
This commit is contained in:
parent
f7777012b9
commit
a6b46660d8
6 changed files with 80 additions and 50 deletions
|
@ -50,6 +50,9 @@ public class AppPreferences {
|
||||||
public String getSystemKey(int number){ return preferences.get("key_area_key_system_0"+number, "");}
|
public String getSystemKey(int number){ return preferences.get("key_area_key_system_0"+number, "");}
|
||||||
public void setSystemKey(int number, String key){ preferences.put("key_area_key_system_0"+number, key); }
|
public void setSystemKey(int number, String key){ preferences.put("key_area_key_system_0"+number, key); }
|
||||||
|
|
||||||
|
public String getTitleKek(int number){ return preferences.get("titlekek_"+number, "");}
|
||||||
|
public void setTitleKek(int number, String key){ preferences.put("titlekek_"+number, key); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public int getTitleKeysCount(){ // TODO: do the same for other multi-keys and single
|
public int getTitleKeysCount(){ // TODO: do the same for other multi-keys and single
|
||||||
|
|
|
@ -76,11 +76,11 @@ public class NCAController implements TabController {
|
||||||
this.selectedFile = file;
|
this.selectedFile = file;
|
||||||
HashMap<String, String> keysMap = new HashMap<>();
|
HashMap<String, String> keysMap = new HashMap<>();
|
||||||
keysMap.put("header_key", AppPreferences.getInstance().getHeaderKey());
|
keysMap.put("header_key", AppPreferences.getInstance().getHeaderKey());
|
||||||
for (int i = 0; i < 8; i++){
|
for (int i = 0; i < 8; i++){ // TODO: FIX!!!!!!!!! URGENT!
|
||||||
keysMap.put("key_area_key_application_0"+i, AppPreferences.getInstance().getApplicationKey(i));
|
keysMap.put("key_area_key_application_0"+i, AppPreferences.getInstance().getApplicationKey(i));
|
||||||
keysMap.put("key_area_key_ocean_0"+i, AppPreferences.getInstance().getOceanKey(i));
|
keysMap.put("key_area_key_ocean_0"+i, AppPreferences.getInstance().getOceanKey(i));
|
||||||
keysMap.put("key_area_key_system_0"+i, AppPreferences.getInstance().getSystemKey(i));
|
keysMap.put("key_area_key_system_0"+i, AppPreferences.getInstance().getSystemKey(i));
|
||||||
// TODO: Add titlekeys
|
keysMap.put("titlekek_0"+i, AppPreferences.getInstance().getTitleKek(i));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < AppPreferences.getInstance().getTitleKeysCount(); i++){
|
for (int i = 0; i < AppPreferences.getInstance().getTitleKeysCount(); i++){
|
||||||
String[] pair = AppPreferences.getInstance().getTitleKeyPair(i);
|
String[] pair = AppPreferences.getInstance().getTitleKeyPair(i);
|
||||||
|
|
|
@ -25,6 +25,7 @@ public class SettingsController implements Initializable {
|
||||||
ListSelectorKAEKAppController,
|
ListSelectorKAEKAppController,
|
||||||
ListSelectorKAEKOceanController,
|
ListSelectorKAEKOceanController,
|
||||||
ListSelectorKAEKSysController,
|
ListSelectorKAEKSysController,
|
||||||
|
ListSelectorTitleKeksController,
|
||||||
ListSelectorTitleKeysController;
|
ListSelectorTitleKeysController;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -37,6 +38,7 @@ public class SettingsController implements Initializable {
|
||||||
ListSelectorKAEKAppController.initSelector(32, "key_area_key_application_");
|
ListSelectorKAEKAppController.initSelector(32, "key_area_key_application_");
|
||||||
ListSelectorKAEKOceanController.initSelector(32, "key_area_key_ocean_");
|
ListSelectorKAEKOceanController.initSelector(32, "key_area_key_ocean_");
|
||||||
ListSelectorKAEKSysController.initSelector(32, "key_area_key_system_");
|
ListSelectorKAEKSysController.initSelector(32, "key_area_key_system_");
|
||||||
|
ListSelectorTitleKeksController.initSelector(32, "titlekek_");
|
||||||
ListSelectorTitleKeysController.initSelector(32, null); // 32 required
|
ListSelectorTitleKeysController.initSelector(32, null); // 32 required
|
||||||
|
|
||||||
LinkedHashMap<String, String> preparedPairsMapInit = new LinkedHashMap<>();
|
LinkedHashMap<String, String> preparedPairsMapInit = new LinkedHashMap<>();
|
||||||
|
@ -57,6 +59,14 @@ public class SettingsController implements Initializable {
|
||||||
}
|
}
|
||||||
ListSelectorKAEKOceanController.setList(preparedPairsMapInit);
|
ListSelectorKAEKOceanController.setList(preparedPairsMapInit);
|
||||||
|
|
||||||
|
preparedPairsMapInit.clear();
|
||||||
|
cnt = 0;
|
||||||
|
while (!(kaekApp = AppPreferences.getInstance().getTitleKek(cnt)).isEmpty()){
|
||||||
|
preparedPairsMapInit.put("titlekek_"+String.format("%02d", cnt), kaekApp);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
ListSelectorTitleKeksController.setList(preparedPairsMapInit);
|
||||||
|
|
||||||
preparedPairsMapInit.clear();
|
preparedPairsMapInit.clear();
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
while (!(kaekApp = AppPreferences.getInstance().getSystemKey(cnt)).isEmpty()){
|
while (!(kaekApp = AppPreferences.getInstance().getSystemKey(cnt)).isEmpty()){
|
||||||
|
@ -129,6 +139,14 @@ public class SettingsController implements Initializable {
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
ListSelectorKAEKSysController.setList(kaekSingle);
|
ListSelectorKAEKSysController.setList(kaekSingle);
|
||||||
|
|
||||||
|
kaekSingle.clear();
|
||||||
|
counter = 0;
|
||||||
|
while ((keyParsed = fileMap.get("titlekek_"+String.format("%02d", counter))) != null){
|
||||||
|
kaekSingle.put("titlekek_"+String.format("%02d", counter), keyParsed);
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
ListSelectorTitleKeksController.setList(kaekSingle);
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException ioe){
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
|
@ -198,6 +216,12 @@ public class SettingsController implements Initializable {
|
||||||
AppPreferences.getInstance().setSystemKey(i, kaekSysKeySet[i].split("\\s=\\s", 2)[1]);
|
AppPreferences.getInstance().setSystemKey(i, kaekSysKeySet[i].split("\\s=\\s", 2)[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String[] titleKekSet = ListSelectorTitleKeksController.getList();
|
||||||
|
if (titleKekSet != null){
|
||||||
|
for (int i = 0; i < titleKekSet.length; i++)
|
||||||
|
AppPreferences.getInstance().setTitleKek(i, titleKekSet[i].split("\\s=\\s", 2)[1]);
|
||||||
|
}
|
||||||
|
|
||||||
String[] titleKeysSet = ListSelectorTitleKeysController.getList();
|
String[] titleKeysSet = ListSelectorTitleKeysController.getList();
|
||||||
if (titleKeysSet != null){
|
if (titleKeysSet != null){
|
||||||
AppPreferences.getInstance().setTitleKeysCount(titleKeysSet.length);
|
AppPreferences.getInstance().setTitleKeysCount(titleKeysSet.length);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package konogonka.Tools.NCA;
|
package konogonka.Tools.NCA;
|
||||||
|
|
||||||
|
import konogonka.LoperConverter;
|
||||||
import konogonka.Tools.NCA.NCASectionTableBlock.NCASectionBlock;
|
import konogonka.Tools.NCA.NCASectionTableBlock.NCASectionBlock;
|
||||||
import konogonka.xtsaes.XTSAESCipher;
|
import konogonka.xtsaes.XTSAESCipher;
|
||||||
import org.bouncycastle.crypto.params.KeyParameter;
|
import org.bouncycastle.crypto.params.KeyParameter;
|
||||||
|
@ -11,6 +12,7 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import static konogonka.LoperConverter.byteArrToHexString;
|
||||||
import static konogonka.LoperConverter.getLElong;
|
import static konogonka.LoperConverter.getLElong;
|
||||||
|
|
||||||
// TODO: check file size
|
// TODO: check file size
|
||||||
|
@ -32,6 +34,8 @@ public class NCAProvider {
|
||||||
private byte cryptoType2; // keyblob index. Considering as number within application/ocean/system
|
private byte cryptoType2; // keyblob index. Considering as number within application/ocean/system
|
||||||
private byte[] rightsId;
|
private byte[] rightsId;
|
||||||
|
|
||||||
|
private byte cryptoTypeReal;
|
||||||
|
|
||||||
private byte[] sha256hash0;
|
private byte[] sha256hash0;
|
||||||
private byte[] sha256hash1;
|
private byte[] sha256hash1;
|
||||||
private byte[] sha256hash2;
|
private byte[] sha256hash2;
|
||||||
|
@ -152,32 +156,28 @@ public class NCAProvider {
|
||||||
encryptedKey2 = Arrays.copyOfRange(encryptedKeysArea, 0x20, 0x30);
|
encryptedKey2 = Arrays.copyOfRange(encryptedKeysArea, 0x20, 0x30);
|
||||||
encryptedKey3 = Arrays.copyOfRange(encryptedKeysArea, 0x30, 0x40);
|
encryptedKey3 = Arrays.copyOfRange(encryptedKeysArea, 0x30, 0x40);
|
||||||
|
|
||||||
|
// Calculate real Crypto Type
|
||||||
|
if (cryptoType1 < cryptoType2)
|
||||||
|
cryptoTypeReal = cryptoType2;
|
||||||
|
else
|
||||||
|
cryptoTypeReal = cryptoType1;
|
||||||
|
|
||||||
|
if (cryptoTypeReal > 0) // TODO: CLARIFY WHY THEH FUCK IS IT FAIR????
|
||||||
|
cryptoTypeReal -= 1;
|
||||||
|
|
||||||
//todo: if nca3 proceed
|
//todo: if nca3 proceed
|
||||||
// If no rights ID (ticket?) exists
|
// Decrypt keys if encrypted
|
||||||
if (Arrays.equals(rightsId, new byte[0x10])) {
|
if (Arrays.equals(rightsId, new byte[0x10])) {
|
||||||
byte realCryptoType;
|
|
||||||
if (cryptoType1 < cryptoType2)
|
|
||||||
realCryptoType = cryptoType2;
|
|
||||||
else
|
|
||||||
realCryptoType = cryptoType1;
|
|
||||||
|
|
||||||
if (realCryptoType > 0) // TODO: CLARIFY WHY THEH FUCK IS IT FAIR????
|
|
||||||
realCryptoType -= 1;
|
|
||||||
|
|
||||||
|
|
||||||
String keyAreaKey;
|
String keyAreaKey;
|
||||||
switch (keyIndex){
|
switch (keyIndex){
|
||||||
case 0:
|
case 0:
|
||||||
keyAreaKey = keys.get("key_area_key_application_0"+realCryptoType);
|
keyAreaKey = keys.get("key_area_key_application_"+String.format("%02d", cryptoTypeReal));
|
||||||
System.out.println("Using key_area_key_application_0"+realCryptoType);
|
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
keyAreaKey = keys.get("key_area_key_ocean_0"+realCryptoType);
|
keyAreaKey = keys.get("key_area_key_ocean_"+String.format("%02d", cryptoTypeReal));
|
||||||
System.out.println("Using key_area_key_ocean_0"+realCryptoType);
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
keyAreaKey = keys.get("key_area_key_system_0"+realCryptoType);
|
keyAreaKey = keys.get("key_area_key_system_"+String.format("%02d", cryptoTypeReal));
|
||||||
System.out.println("Using key_area_key_system_0"+realCryptoType);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
keyAreaKey = null;
|
keyAreaKey = null;
|
||||||
|
@ -193,11 +193,6 @@ public class NCAProvider {
|
||||||
decryptedKey3 = cipher.doFinal(encryptedKey3);
|
decryptedKey3 = cipher.doFinal(encryptedKey3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
tableEntry0 = new NCAHeaderTableEntry(tableBytes);
|
tableEntry0 = new NCAHeaderTableEntry(tableBytes);
|
||||||
tableEntry1 = new NCAHeaderTableEntry(Arrays.copyOfRange(tableBytes, 0x10, 0x20));
|
tableEntry1 = new NCAHeaderTableEntry(Arrays.copyOfRange(tableBytes, 0x10, 0x20));
|
||||||
|
@ -253,33 +248,39 @@ public class NCAProvider {
|
||||||
* @param sectionNumber should be 1-4
|
* @param sectionNumber should be 1-4
|
||||||
* */
|
* */
|
||||||
public NCAContentPFS0 getNCAContentPFS0(int sectionNumber){
|
public NCAContentPFS0 getNCAContentPFS0(int sectionNumber){
|
||||||
// TODO: provide titleKey if needed
|
byte[] key;
|
||||||
|
|
||||||
switch (sectionNumber){
|
// If empty Rights ID
|
||||||
|
if (Arrays.equals(rightsId, new byte[0x10])) {
|
||||||
|
key = decryptedKey2; // TODO: Just remember this dumb hach
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
byte[] rightsIDkey = hexStrToByteArray(keys.get(byteArrToHexString(rightsId)));
|
||||||
|
|
||||||
|
try {
|
||||||
|
SecretKeySpec skSpec = new SecretKeySpec(
|
||||||
|
hexStrToByteArray(keys.get("titlekek_"+String.format("%02d", cryptoTypeReal))
|
||||||
|
), "AES");
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, skSpec);
|
||||||
|
key = cipher.doFinal(rightsIDkey);
|
||||||
|
}
|
||||||
|
catch (Exception e){
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch (sectionNumber) {
|
||||||
case 0:
|
case 0:
|
||||||
return new NCAContentPFS0(file, offset, sectionBlock0, tableEntry0, decryptedKey2); // TODO: remove decryptedKey2
|
return new NCAContentPFS0(file, offset, sectionBlock0, tableEntry0, key); // TODO: remove decryptedKey2
|
||||||
case 1:
|
case 1:
|
||||||
return new NCAContentPFS0(file, offset, sectionBlock1, tableEntry1, decryptedKey2);
|
return new NCAContentPFS0(file, offset, sectionBlock1, tableEntry1, key);
|
||||||
case 2:
|
case 2:
|
||||||
return new NCAContentPFS0(file, offset, sectionBlock2, tableEntry2, decryptedKey2);
|
return new NCAContentPFS0(file, offset, sectionBlock2, tableEntry2, key);
|
||||||
case 3:
|
case 3:
|
||||||
return new NCAContentPFS0(file, offset, sectionBlock3, tableEntry3, decryptedKey2);
|
return new NCAContentPFS0(file, offset, sectionBlock3, tableEntry3, key);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 0 OR 2 crypto type
|
|
||||||
// 0,1,2 kaek index
|
|
||||||
//settings.keyset.key_area_keys[ctx->crypto_type][ctx->header.kaek_ind]
|
|
||||||
/*
|
|
||||||
0x207 =
|
|
||||||
0: key_area_key_application_ 0x206 range:[0-6]; usually used 0 or 2
|
|
||||||
1: key_area_key_ocean [0-6]
|
|
||||||
2: key_area_key_system [0-6]
|
|
||||||
|
|
||||||
if(ncahdr_x206 < ncahdr_x220){ret = ncahdr_x220; } else { ret = ncahdr_x206; } return ret;
|
|
||||||
|
|
||||||
ret > 0? ret--
|
|
||||||
|
|
||||||
*/
|
|
|
@ -48,15 +48,18 @@
|
||||||
<Label disable="true" text="Length should be 64 symbols" wrapText="true" />
|
<Label disable="true" text="Length should be 64 symbols" wrapText="true" />
|
||||||
<Pane VBox.vgrow="ALWAYS" />
|
<Pane VBox.vgrow="ALWAYS" />
|
||||||
<Separator prefWidth="200.0" />
|
<Separator prefWidth="200.0" />
|
||||||
<Label text="Label" />
|
<Label text="Key area key "Application"" />
|
||||||
<fx:include fx:id="ListSelectorKAEKApp" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
<fx:include fx:id="ListSelectorKAEKApp" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
||||||
<Separator prefWidth="200.0" />
|
<Separator prefWidth="200.0" />
|
||||||
<Label text="Label" />
|
<Label text="Key area key "Ocean"" />
|
||||||
<fx:include fx:id="ListSelectorKAEKOcean" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
<fx:include fx:id="ListSelectorKAEKOcean" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
||||||
<Separator prefWidth="200.0" />
|
<Separator prefWidth="200.0" />
|
||||||
<Label text="Label" />
|
<Label text="Key area key "System"" />
|
||||||
<fx:include fx:id="ListSelectorKAEKSys" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
<fx:include fx:id="ListSelectorKAEKSys" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
||||||
<Separator prefWidth="200.0" />
|
<Separator prefWidth="200.0" />
|
||||||
|
<Label text="Title KEKs" />
|
||||||
|
<fx:include fx:id="ListSelectorTitleKeks" source="ListSelectorLayout.fxml" VBox.vgrow="ALWAYS" />
|
||||||
|
<Separator prefWidth="200.0" />
|
||||||
</children>
|
</children>
|
||||||
<padding>
|
<padding>
|
||||||
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
|
||||||
|
@ -108,8 +111,7 @@
|
||||||
</TabPane>
|
</TabPane>
|
||||||
<ButtonBar>
|
<ButtonBar>
|
||||||
<buttons>
|
<buttons>
|
||||||
|
<Button fx:id="okBtn" mnemonicParsing="false" text="Ok" />
|
||||||
<Button fx:id="okBtn" mnemonicParsing="false" text="Ok" />
|
|
||||||
<Button fx:id="cancelBtn" mnemonicParsing="false" text="Cancel" />
|
<Button fx:id="cancelBtn" mnemonicParsing="false" text="Cancel" />
|
||||||
</buttons>
|
</buttons>
|
||||||
<padding>
|
<padding>
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 24 KiB |
Loading…
Reference in a new issue