movements to implementing encrypted sections PFS0 provider

This commit is contained in:
Dmitry Isaenko 2019-05-20 01:54:46 +03:00
parent 8e5871d2b3
commit f1c38e9e4c
3 changed files with 103 additions and 16 deletions

View file

@ -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

View file

@ -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.");
}
}
}
} }

View file

@ -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; }