movements to implementing encrypted sections PFS0 provider
This commit is contained in:
parent
8e5871d2b3
commit
f1c38e9e4c
3 changed files with 103 additions and 16 deletions
|
@ -7,6 +7,7 @@ Deep WIP multi-tool to work with XCI/NSP/NCA/NRO(?) files
|
||||||
[GNU General Public License v3](https://github.com/developersu/konogonka/blob/master/LICENSE)
|
[GNU General Public License v3](https://github.com/developersu/konogonka/blob/master/LICENSE)
|
||||||
|
|
||||||
### Used libraries & resources
|
### Used libraries & resources
|
||||||
|
* [Bouncy Castle](https://www.bouncycastle.org/) for Java.
|
||||||
* [Java-XTS-AES](https://github.com/horrorho/Java-XTS-AES) by horrorho with minimal changes.
|
* [Java-XTS-AES](https://github.com/horrorho/Java-XTS-AES) by horrorho with minimal changes.
|
||||||
* [OpenJFX](https://wiki.openjdk.java.net/display/OpenJFX/Main)
|
* [OpenJFX](https://wiki.openjdk.java.net/display/OpenJFX/Main)
|
||||||
* Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/)
|
* Few icons taken from: [materialdesignicons.com](http://materialdesignicons.com/)
|
||||||
|
@ -14,3 +15,7 @@ Deep WIP multi-tool to work with XCI/NSP/NCA/NRO(?) files
|
||||||
### System requirements
|
### System requirements
|
||||||
|
|
||||||
JRE/JDK 8u60 or higher.
|
JRE/JDK 8u60 or higher.
|
||||||
|
|
||||||
|
### Thanks
|
||||||
|
|
||||||
|
TBD
|
|
@ -6,8 +6,7 @@ import konogonka.Tools.NCA.NCASectionTableBlock.NCASectionBlock;
|
||||||
import konogonka.Tools.PFS0.PFS0Provider;
|
import konogonka.Tools.PFS0.PFS0Provider;
|
||||||
import konogonka.ctraes.AesCtr;
|
import konogonka.ctraes.AesCtr;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
@ -86,22 +85,29 @@ public class NCAContentPFS0 {
|
||||||
|
|
||||||
byte[] encryptedBlock;
|
byte[] encryptedBlock;
|
||||||
byte[] dectyptedBlock;
|
byte[] dectyptedBlock;
|
||||||
long mediaBlockSize = ncaHeaderTableEntry.getMediaEndOffset()-ncaHeaderTableEntry.getMediaStartOffset();
|
long mediaBlockSize = ncaHeaderTableEntry.getMediaEndOffset() - ncaHeaderTableEntry.getMediaStartOffset();
|
||||||
|
// Prepare thread to parse encrypted data
|
||||||
int j = 0;
|
PipedOutputStream streamOut = new PipedOutputStream();
|
||||||
|
PipedInputStream streamInp = new PipedInputStream(streamOut);
|
||||||
|
|
||||||
|
new Thread(new ParseEncrypted(
|
||||||
|
SHA256hashes,
|
||||||
|
streamInp,
|
||||||
|
ncaSectionBlock.getSuperBlockPFS0().getPfs0offset(),
|
||||||
|
ncaSectionBlock.getSuperBlockPFS0().getPfs0size(),
|
||||||
|
ncaSectionBlock.getSuperBlockPFS0().getHashTableOffset(),
|
||||||
|
ncaSectionBlock.getSuperBlockPFS0().getHashTableSize()
|
||||||
|
)).start();
|
||||||
|
// Decrypt data
|
||||||
for (int i = 0; i < mediaBlockSize; i++){
|
for (int i = 0; i < mediaBlockSize; i++){
|
||||||
encryptedBlock = new byte[0x200];
|
encryptedBlock = new byte[0x200];
|
||||||
if (raf.read(encryptedBlock) != -1){
|
if (raf.read(encryptedBlock) != -1){
|
||||||
dectyptedBlock = aesCtr.decrypt(encryptedBlock);
|
dectyptedBlock = aesCtr.decrypt(encryptedBlock);
|
||||||
|
// Writing decrypted data to pipe
|
||||||
System.out.println(new String(dectyptedBlock, (int)ncaSectionBlock.getSuperBlockPFS0().getPfs0offset(), 0x4, StandardCharsets.US_ASCII));
|
streamOut.write(dectyptedBlock);
|
||||||
/*
|
|
||||||
*/
|
|
||||||
j++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
streamOut.flush();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
System.arraycopy(dectyptedBlock, 0, decryptedHeader, i * 0x200, 0x200);
|
System.arraycopy(dectyptedBlock, 0, decryptedHeader, i * 0x200, 0x200);
|
||||||
|
@ -163,4 +169,84 @@ public class NCAContentPFS0 {
|
||||||
|
|
||||||
public LinkedList<byte[]> getSHA256hashes() { return SHA256hashes; }
|
public LinkedList<byte[]> getSHA256hashes() { return SHA256hashes; }
|
||||||
public PFS0Provider getPfs0() { return pfs0; }
|
public PFS0Provider getPfs0() { return pfs0; }
|
||||||
|
|
||||||
|
|
||||||
|
private class ParseEncrypted implements Runnable{
|
||||||
|
|
||||||
|
LinkedList<byte[]> SHA256hashes;
|
||||||
|
PipedInputStream pipedInputStream;
|
||||||
|
|
||||||
|
long hashTableOffset;
|
||||||
|
long hashTableSize;
|
||||||
|
long hashTableRecordsCount;
|
||||||
|
long pfs0offset;
|
||||||
|
long pfs0size;
|
||||||
|
|
||||||
|
ParseEncrypted(LinkedList<byte[]> SHA256hashes, PipedInputStream pipedInputStream, long pfs0offset, long pfs0size, long hashTableOffset, long hashTableSize){
|
||||||
|
this.SHA256hashes = SHA256hashes;
|
||||||
|
this.pipedInputStream = pipedInputStream;
|
||||||
|
this.hashTableOffset = hashTableOffset;
|
||||||
|
this.hashTableSize = hashTableSize;
|
||||||
|
this.hashTableRecordsCount = hashTableSize / 0x20;
|
||||||
|
this.pfs0offset = pfs0offset;
|
||||||
|
this.pfs0size = pfs0size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
long counter = 0; // How many bytes already read
|
||||||
|
|
||||||
|
try{
|
||||||
|
if (hashTableOffset > 0){
|
||||||
|
while (counter < hashTableOffset) {
|
||||||
|
pipedInputStream.read();
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Main loop
|
||||||
|
while (true){
|
||||||
|
// Loop for collecting all recrods from sha256 hash table
|
||||||
|
while ((counter - hashTableOffset) < hashTableSize){
|
||||||
|
int hashCounter = 0;
|
||||||
|
byte[] sectionHash = new byte[0x20];
|
||||||
|
// Loop for collecting bytes for every SINGLE records, where record size == 0x20
|
||||||
|
while (hashCounter < 0x20){
|
||||||
|
int currentByte = pipedInputStream.read();
|
||||||
|
if (currentByte == -1)
|
||||||
|
break;
|
||||||
|
sectionHash[hashCounter] = (byte)currentByte;
|
||||||
|
hashCounter++;
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
// Write after collecting
|
||||||
|
SHA256hashes.add(sectionHash);
|
||||||
|
}
|
||||||
|
// Skip padding and go to PFS0 location
|
||||||
|
if (counter < pfs0offset){
|
||||||
|
while (counter < pfs0offset){
|
||||||
|
pipedInputStream.read();
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------
|
||||||
|
byte[] magic = new byte[0x4];
|
||||||
|
for (int i = 0; i < 4; i++){
|
||||||
|
int currentByte = pipedInputStream.read();
|
||||||
|
if (currentByte == -1)
|
||||||
|
break;
|
||||||
|
magic[i] = (byte)currentByte;
|
||||||
|
}
|
||||||
|
RainbowHexDump.hexDumpUTF8(magic);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException ioe){
|
||||||
|
System.out.println("'ParseEncrypted' thread exception");
|
||||||
|
ioe.printStackTrace();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
System.out.println("Thread died.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,6 @@ import java.util.Arrays;
|
||||||
import static konogonka.LoperConverter.*;
|
import static konogonka.LoperConverter.*;
|
||||||
|
|
||||||
public class PFS0Provider {
|
public class PFS0Provider {
|
||||||
private long pfs0offsetPosition;
|
|
||||||
private long rawFileDataStart;
|
private long rawFileDataStart;
|
||||||
|
|
||||||
private String magic;
|
private String magic;
|
||||||
|
@ -23,8 +22,6 @@ public class PFS0Provider {
|
||||||
public PFS0Provider(File fileWithPfs0) throws Exception{ this(fileWithPfs0, 0); }
|
public PFS0Provider(File fileWithPfs0) throws Exception{ this(fileWithPfs0, 0); }
|
||||||
|
|
||||||
public PFS0Provider(File fileWithPfs0, long pfs0offsetPosition) throws Exception{
|
public PFS0Provider(File fileWithPfs0, long pfs0offsetPosition) throws Exception{
|
||||||
this.pfs0offsetPosition = pfs0offsetPosition;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
RandomAccessFile raf = new RandomAccessFile(fileWithPfs0, "r");
|
RandomAccessFile raf = new RandomAccessFile(fileWithPfs0, "r");
|
||||||
|
|
||||||
|
@ -101,7 +98,6 @@ public class PFS0Provider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getPfs0offsetPosition() { return pfs0offsetPosition; }
|
|
||||||
public String getMagic() { return magic; }
|
public String getMagic() { return magic; }
|
||||||
public int getFilesCount() { return filesCount; }
|
public int getFilesCount() { return filesCount; }
|
||||||
public int getStringTableSize() { return stringTableSize; }
|
public int getStringTableSize() { return stringTableSize; }
|
||||||
|
|
Loading…
Reference in a new issue