Move the decryption of a inputstream into a output stream in the NUSDecryption class.

This commit is contained in:
Maschell 2019-04-11 13:28:12 +02:00
parent fbceae0558
commit 8c75a1a43e
2 changed files with 49 additions and 42 deletions

View File

@ -95,7 +95,12 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
InputStream in = dataProvider.getInputStreamFromContent(c, fileOffsetBlock);
try {
return decryptStreams(in, outputStream, fileSize, fileOffset, c);
NUSDecryption nusdecryption = new NUSDecryption(title.getTicket());
Optional<byte[]> h3HashedOpt = Optional.empty();
if (c.isHashed()) {
h3HashedOpt = dataProvider.getContentH3Hash(c);
}
return nusdecryption.decryptStreams(in, outputStream, fileSize, fileOffset, c, h3HashedOpt);
} catch (CheckSumWrongException e) {
if (entry.getContent().isUNKNWNFlag1Set()) {
log.info("Hash doesn't match. But file is optional. Don't worry.");
@ -115,47 +120,6 @@ public class FSTDataProviderNUSTitle implements FSTDataProvider, HasNUSTitle {
return false;
}
private boolean decryptStreams(InputStream inputStream, OutputStream outputStream, long size, long offset, Content content)
throws IOException, CheckSumWrongException {
NUSDecryption nusdecryption = new NUSDecryption(title.getTicket());
short contentIndex = (short) content.getIndex();
long encryptedFileSize = content.getEncryptedFileSize();
if (content.isEncrypted()) {
if (content.isHashed()) {
NUSDataProvider dataProvider = title.getDataProvider();
byte[] h3 = dataProvider.getContentH3Hash(content).orElseThrow(() -> new FileNotFoundException("h3 hash not found."));
nusdecryption.decryptFileStreamHashed(inputStream, outputStream, size, offset, (short) contentIndex, h3);
} else {
try {
byte[] h3Hash = content.getSHA2Hash();
// We want to check if we read the whole file or just a part of it.
// There should be only one actual file inside a non-hashed content.
// But it could also contain a directory, so we need to filter.
long fstFileSize = content.getEntries().stream().filter(f -> !f.isDir()).findFirst().map(f -> f.getFileSize()).orElse(0L);
if (size > 0 && size < fstFileSize) {
h3Hash = null;
}
nusdecryption.decryptFileStream(inputStream, outputStream, size, offset, (short) contentIndex, h3Hash, encryptedFileSize);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
StreamUtils.saveInputStreamToOutputStreamWithHash(inputStream, outputStream, size, content.getSHA2Hash(), encryptedFileSize);
}
synchronized (inputStream) {
inputStream.close();
}
synchronized (outputStream) {
outputStream.close();
}
return true;
}
@Override
public NUSTitle getNUSTitle() {
return title;

View File

@ -16,6 +16,7 @@
****************************************************************************/
package de.mas.wiiu.jnus.utils.cryptography;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@ -23,8 +24,10 @@ import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Optional;
import de.mas.wiiu.jnus.entities.Ticket;
import de.mas.wiiu.jnus.entities.content.Content;
import de.mas.wiiu.jnus.utils.ByteArrayBuffer;
import de.mas.wiiu.jnus.utils.CheckSumWrongException;
import de.mas.wiiu.jnus.utils.HashUtil;
@ -263,4 +266,44 @@ public class NUSDecryption extends AESDecryption {
return output;
}
public boolean decryptStreams(InputStream inputStream, OutputStream outputStream, long size, long offset, Content content, Optional<byte[]> h3HashHashed)
throws IOException, CheckSumWrongException {
short contentIndex = (short) content.getIndex();
long encryptedFileSize = content.getEncryptedFileSize();
if (content.isEncrypted()) {
if (content.isHashed()) {
byte[] h3 = h3HashHashed.orElseThrow(() -> new FileNotFoundException("h3 hash not found."));
decryptFileStreamHashed(inputStream, outputStream, size, offset, (short) contentIndex, h3);
} else {
try {
byte[] h3Hash = content.getSHA2Hash();
// We want to check if we read the whole file or just a part of it.
// There should be only one actual file inside a non-hashed content.
// But it could also contain a directory, so we need to filter.
long fstFileSize = content.getEntries().stream().filter(f -> !f.isDir()).findFirst().map(f -> f.getFileSize()).orElse(0L);
if (size > 0 && size < fstFileSize) {
h3Hash = null;
}
decryptFileStream(inputStream, outputStream, size, offset, (short) contentIndex, h3Hash, encryptedFileSize);
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
StreamUtils.saveInputStreamToOutputStreamWithHash(inputStream, outputStream, size, content.getSHA2Hash(), encryptedFileSize);
}
synchronized (inputStream) {
inputStream.close();
}
synchronized (outputStream) {
outputStream.close();
}
return true;
}
}