diff --git a/src/main/java/libKonogonka/Converter.java b/src/main/java/libKonogonka/Converter.java
index a52ed93..053e6a0 100644
--- a/src/main/java/libKonogonka/Converter.java
+++ b/src/main/java/libKonogonka/Converter.java
@@ -89,16 +89,13 @@ public class Converter {
}
public static byte[] hexStringToByteArray(String string){
- if (string.length() % 2 != 0)
- string = "0" + string;
-
- int resultSize = string.length() / 2;
- byte[] resultingArray = new byte[resultSize];
-
- for (int i = 0; i < resultSize; i++){
- resultingArray[i] = (byte) Integer.parseInt(string.substring(i*2, i*2+2), 16);
+ int len = string.length();
+ byte[] data = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ data[i / 2] = (byte) ((Character.digit(string.charAt(i), 16) << 4)
+ + Character.digit(string.charAt(i+1), 16));
}
- return resultingArray;
+ return data;
}
public static byte[] flip(byte[] bytes){
diff --git a/src/main/java/libKonogonka/Tools/ISuperProvider.java b/src/main/java/libKonogonka/Tools/ISuperProvider.java
index 27b3822..b6b46a6 100644
--- a/src/main/java/libKonogonka/Tools/ISuperProvider.java
+++ b/src/main/java/libKonogonka/Tools/ISuperProvider.java
@@ -18,7 +18,7 @@
*/
package libKonogonka.Tools;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import java.io.File;
diff --git a/src/main/java/libKonogonka/Tools/NCA/NCAContent.java b/src/main/java/libKonogonka/Tools/NCA/NCAContent.java
index 4052b35..9451d5b 100644
--- a/src/main/java/libKonogonka/Tools/NCA/NCAContent.java
+++ b/src/main/java/libKonogonka/Tools/NCA/NCAContent.java
@@ -21,9 +21,9 @@ package libKonogonka.Tools.NCA;
import libKonogonka.Tools.NCA.NCASectionTableBlock.NcaFsHeader;
import libKonogonka.Tools.PFS0.PFS0Provider;
import libKonogonka.Tools.RomFs.RomFsProvider;
-import libKonogonka.ctraes.AesCtrBufferedInputStream;
-import libKonogonka.ctraes.AesCtrDecryptForMediaBlocks;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.AesCtrBufferedInputStream;
+import libKonogonka.aesctr.AesCtrDecryptForMediaBlocks;
+import libKonogonka.aesctr.InFileStreamProducer;
import libKonogonka.exceptions.EmptySectionException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
diff --git a/src/main/java/libKonogonka/Tools/NCA/NCASectionTableBlock/NcaFsHeader.java b/src/main/java/libKonogonka/Tools/NCA/NCASectionTableBlock/NcaFsHeader.java
index 3419d66..dda045e 100644
--- a/src/main/java/libKonogonka/Tools/NCA/NCASectionTableBlock/NcaFsHeader.java
+++ b/src/main/java/libKonogonka/Tools/NCA/NCASectionTableBlock/NcaFsHeader.java
@@ -18,6 +18,7 @@
*/
package libKonogonka.Tools.NCA.NCASectionTableBlock;
+import libKonogonka.Converter;
import libKonogonka.RainbowDump;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -82,7 +83,7 @@ public class NcaFsHeader {
generation = Arrays.copyOfRange(tableBlockBytes, 0x140, 0x144);
secureValue = Arrays.copyOfRange(tableBlockBytes, 0x144, 0x148);
- sectionCTR = Arrays.copyOfRange(tableBlockBytes, 0x140, 0x148);
+ sectionCTR = Converter.flip(Arrays.copyOfRange(tableBlockBytes, 0x140, 0x148));
sparseInfo = new SparseInfo(Arrays.copyOfRange(tableBlockBytes, 0x148, 0x178));
compressionInfo = new CompressionInfo(Arrays.copyOfRange(tableBlockBytes, 0x178, 0x1a0));
diff --git a/src/main/java/libKonogonka/Tools/NPDM/NPDMProvider.java b/src/main/java/libKonogonka/Tools/NPDM/NPDMProvider.java
index b930c74..6fe4d88 100644
--- a/src/main/java/libKonogonka/Tools/NPDM/NPDMProvider.java
+++ b/src/main/java/libKonogonka/Tools/NPDM/NPDMProvider.java
@@ -20,7 +20,7 @@ package libKonogonka.Tools.NPDM;
import libKonogonka.Tools.NPDM.ACI0.ACI0Provider;
import libKonogonka.Tools.NPDM.ACID.ACIDProvider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import java.io.BufferedInputStream;
import java.io.File;
diff --git a/src/main/java/libKonogonka/Tools/NSO/NSO0Provider.java b/src/main/java/libKonogonka/Tools/NSO/NSO0Provider.java
index cbb9567..adb5794 100644
--- a/src/main/java/libKonogonka/Tools/NSO/NSO0Provider.java
+++ b/src/main/java/libKonogonka/Tools/NSO/NSO0Provider.java
@@ -18,7 +18,7 @@
*/
package libKonogonka.Tools.NSO;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import java.io.BufferedInputStream;
import java.io.File;
diff --git a/src/main/java/libKonogonka/Tools/NSO/NSO0Unpacker.java b/src/main/java/libKonogonka/Tools/NSO/NSO0Unpacker.java
index a26b625..8e47b0b 100644
--- a/src/main/java/libKonogonka/Tools/NSO/NSO0Unpacker.java
+++ b/src/main/java/libKonogonka/Tools/NSO/NSO0Unpacker.java
@@ -18,7 +18,7 @@
*/
package libKonogonka.Tools.NSO;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import net.jpountz.lz4.LZ4Factory;
import net.jpountz.lz4.LZ4SafeDecompressor;
diff --git a/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java b/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java
index 60d3a6f..461439f 100644
--- a/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java
+++ b/src/main/java/libKonogonka/Tools/PFS0/PFS0Provider.java
@@ -22,13 +22,11 @@ import libKonogonka.RainbowDump;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.ISuperProvider;
import libKonogonka.Tools.NCA.NCASectionTableBlock.SuperBlockPFS0;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.util.LinkedList;
public class PFS0Provider extends ExportAble implements ISuperProvider {
diff --git a/src/main/java/libKonogonka/Tools/RomFs/RomFsConstruct.java b/src/main/java/libKonogonka/Tools/RomFs/RomFsConstruct.java
index 2b9da2f..98bfb79 100644
--- a/src/main/java/libKonogonka/Tools/RomFs/RomFsConstruct.java
+++ b/src/main/java/libKonogonka/Tools/RomFs/RomFsConstruct.java
@@ -19,7 +19,7 @@
package libKonogonka.Tools.RomFs;
import libKonogonka.Converter;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import java.io.BufferedInputStream;
diff --git a/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java b/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java
index b90fefd..10062f9 100644
--- a/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java
+++ b/src/main/java/libKonogonka/Tools/RomFs/RomFsProvider.java
@@ -21,7 +21,7 @@ package libKonogonka.Tools.RomFs;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.RomFs.view.DirectoryMetaTablePlainView;
import libKonogonka.Tools.RomFs.view.FileMetaTablePlainView;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
diff --git a/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java b/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java
index 26ca5ee..2cc6000 100644
--- a/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java
+++ b/src/main/java/libKonogonka/Tools/XCI/HFS0Provider.java
@@ -20,14 +20,12 @@ package libKonogonka.Tools.XCI;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.ISuperProvider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.*;
import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.util.Arrays;
import static libKonogonka.Converter.*;
diff --git a/src/main/java/libKonogonka/Tools/other/System2/System2Header.java b/src/main/java/libKonogonka/Tools/other/System2/System2Header.java
index 817913e..a6be53b 100644
--- a/src/main/java/libKonogonka/Tools/other/System2/System2Header.java
+++ b/src/main/java/libKonogonka/Tools/other/System2/System2Header.java
@@ -20,7 +20,7 @@ package libKonogonka.Tools.other.System2;
import libKonogonka.Converter;
import libKonogonka.RainbowDump;
-import libKonogonka.ctraesclassic.AesCtrDecryptClassic;
+import libKonogonka.aesctr.AesCtrDecryptClassic;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
diff --git a/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java b/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java
index 58a1bcb..71f3343 100644
--- a/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java
+++ b/src/main/java/libKonogonka/Tools/other/System2/System2Provider.java
@@ -21,8 +21,8 @@ package libKonogonka.Tools.other.System2;
import libKonogonka.KeyChainHolder;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.other.System2.ini1.Ini1Provider;
-import libKonogonka.ctraes.InFileStreamProducer;
-import libKonogonka.ctraesclassic.InFileStreamClassicProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamClassicProducer;
import java.io.*;
import java.nio.ByteBuffer;
diff --git a/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java b/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java
index 7994eac..ac94341 100644
--- a/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java
+++ b/src/main/java/libKonogonka/Tools/other/System2/ini1/Ini1Provider.java
@@ -20,7 +20,7 @@ package libKonogonka.Tools.other.System2.ini1;
import libKonogonka.Tools.ExportAble;
import libKonogonka.Tools.other.System2.System2Header;
-import libKonogonka.ctraesclassic.InFileStreamClassicProducer;
+import libKonogonka.aesctr.InFileStreamClassicProducer;
import java.io.IOException;
import java.nio.file.Files;
diff --git a/src/main/java/libKonogonka/Tools/other/System2/ini1/KIP1Provider.java b/src/main/java/libKonogonka/Tools/other/System2/ini1/KIP1Provider.java
index 15dc1bb..79b2b75 100644
--- a/src/main/java/libKonogonka/Tools/other/System2/ini1/KIP1Provider.java
+++ b/src/main/java/libKonogonka/Tools/other/System2/ini1/KIP1Provider.java
@@ -19,7 +19,7 @@
package libKonogonka.Tools.other.System2.ini1;
import libKonogonka.Tools.ExportAble;
-import libKonogonka.ctraesclassic.InFileStreamClassicProducer;
+import libKonogonka.aesctr.InFileStreamClassicProducer;
import java.nio.file.Paths;
diff --git a/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1Unpacker.java b/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1Unpacker.java
index f6287c9..a08cdec 100644
--- a/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1Unpacker.java
+++ b/src/main/java/libKonogonka/Tools/other/System2/ini1/Kip1Unpacker.java
@@ -20,7 +20,7 @@ package libKonogonka.Tools.other.System2.ini1;
import libKonogonka.Tools.NSO.SegmentHeader;
import libKonogonka.blz.BlzDecompress;
-import libKonogonka.ctraesclassic.InFileStreamClassicProducer;
+import libKonogonka.aesctr.InFileStreamClassicProducer;
import java.io.BufferedInputStream;
import java.io.File;
diff --git a/src/main/java/libKonogonka/ctraes/AesCtrBufferedInputStream.java b/src/main/java/libKonogonka/aesctr/AesCtrBufferedInputStream.java
similarity index 77%
rename from src/main/java/libKonogonka/ctraes/AesCtrBufferedInputStream.java
rename to src/main/java/libKonogonka/aesctr/AesCtrBufferedInputStream.java
index dd8d759..db2824b 100644
--- a/src/main/java/libKonogonka/ctraes/AesCtrBufferedInputStream.java
+++ b/src/main/java/libKonogonka/aesctr/AesCtrBufferedInputStream.java
@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with libKonogonka. If not, see .
*/
-package libKonogonka.ctraes;
+package libKonogonka.aesctr;
import libKonogonka.RainbowDump;
import org.apache.logging.log4j.LogManager;
@@ -27,15 +27,24 @@ import java.io.*;
public class AesCtrBufferedInputStream extends BufferedInputStream {
private final static Logger log = LogManager.getLogger(AesCtrBufferedInputStream.class);
- private final AesCtrDecryptForMediaBlocks decryptor;
- private final long mediaOffsetPositionStart;
- private final long mediaOffsetPositionEnd;
+ private final AesCtrDecrypt decryptor;
+ private final long encryptedStartOffset;
+ private final long encryptedEndOffset;
private final long fileSize;
private byte[] decryptedBytes;
private long pseudoPos;
private int pointerInsideDecryptedSection;
+ /**
+ * AES CTR for 'Media Blocks'. Used in NCA.
+ * @param decryptor AesCtrDecryptForMediaBlocks
+ * @param ncaOffsetPosition NCA offset in file. If NCA is inside XCI, NSP. Otherwise, must be 0.
+ * @param mediaStartOffset 'Media Start Offset' in NCA representation. Small value, not bytes.
+ * @param mediaEndOffset 'Media End Offset' in NCA representation. Small value, not bytes.
+ * @param inputStream InputStream as it used in regular BufferedInputStream.
+ * @param fileSize File size or InputStream size.
+ */
public AesCtrBufferedInputStream(AesCtrDecryptForMediaBlocks decryptor,
long ncaOffsetPosition,
long mediaStartOffset,
@@ -44,13 +53,36 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
long fileSize){
super(inputStream, 0x200);
this.decryptor = decryptor;
- this.mediaOffsetPositionStart = ncaOffsetPosition + (mediaStartOffset * 0x200);
- this.mediaOffsetPositionEnd = ncaOffsetPosition + (mediaEndOffset * 0x200);
+ this.encryptedStartOffset = ncaOffsetPosition + (mediaStartOffset * 0x200);
+ this.encryptedEndOffset = ncaOffsetPosition + (mediaEndOffset * 0x200);
this.fileSize = fileSize;
log.trace("\n Offset Position "+ncaOffsetPosition+
- "\n MediaOffsetPositionStart "+RainbowDump.formatDecHexString(mediaOffsetPositionStart)+
- "\n MediaOffsetPositionEnd "+RainbowDump.formatDecHexString(mediaOffsetPositionEnd));
+ "\n MediaOffsetPositionStart "+RainbowDump.formatDecHexString(encryptedStartOffset)+
+ "\n MediaOffsetPositionEnd "+RainbowDump.formatDecHexString(encryptedEndOffset));
+ }
+
+ /**
+ * AES CTR 'classic' implementation. Used for system2 (PK21) decrypt.
+ * @param decryptor AesCtrDecryptClassic
+ * @param encryptedStartOffset Encrypted start position in bytes.
+ * @param encryptedEndOffset Encrypted start position in bytes.
+ * @param inputStream InputStream as it used in regular BufferedInputStream
+ * @param fileSize File size or InputStream size.
+ */
+ public AesCtrBufferedInputStream(AesCtrDecryptClassic decryptor,
+ long encryptedStartOffset,
+ long encryptedEndOffset,
+ InputStream inputStream,
+ long fileSize){
+ super(inputStream, 0x200);
+ this.decryptor = decryptor;
+ this.encryptedStartOffset = encryptedStartOffset;
+ this.encryptedEndOffset = encryptedEndOffset;
+ this.fileSize = fileSize;
+
+ log.trace(" EncryptedStartOffset : "+RainbowDump.formatDecHexString(encryptedStartOffset)+
+ "\n EncryptedEndOffset : "+RainbowDump.formatDecHexString(encryptedEndOffset));
}
@Override
@@ -81,7 +113,7 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
System.arraycopy(decryptedBytes, 0, b, bytesFromFirstBlock+i*0x200, 0x200);
}
//3
- if(fileSize > (pseudoPos+ len)) {
+ if(fileSize > (pseudoPos+len)) {
fillDecryptedCache();
System.arraycopy(decryptedBytes, 0, b, bytesFromFirstBlock + middleBlocksCount * 0x200, bytesFromLastBlock);
}
@@ -90,7 +122,7 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
return b.length;
}
log.trace("1. Pointer Inside + End Position Outside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- int middleBlocksCount = (int) ((mediaOffsetPositionEnd - (pseudoPos+bytesFromFirstBlock)) / 0x200);
+ int middleBlocksCount = (int) ((encryptedEndOffset - (pseudoPos+bytesFromFirstBlock)) / 0x200);
int bytesFromEnd = len - bytesFromFirstBlock - middleBlocksCount * 0x200;
//1
System.arraycopy(decryptedBytes, pointerInsideDecryptedSection, b, 0, bytesFromFirstBlock);
@@ -105,10 +137,10 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
pseudoPos += len;
pointerInsideDecryptedSection = 0;
return b.length;
- }
+ }
if (isEndPositionInsideEncryptedSection(len)) {
log.trace("2. End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- int bytesTillEncrypted = (int) (mediaOffsetPositionStart - pseudoPos);
+ int bytesTillEncrypted = (int) (encryptedStartOffset - pseudoPos);
int fullEncryptedBlocks = (len - bytesTillEncrypted) / 0x200;
int incompleteEncryptedBytes = (len - bytesTillEncrypted) % 0x200;
System.arraycopy(readChunk(bytesTillEncrypted), 0, b, 0, bytesTillEncrypted);
@@ -133,34 +165,31 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
try{
decryptedBytes = decryptor.decryptNext(readChunk(0x200));
}
- catch (Exception e){
- throw new IOException(e);
- }
+ catch (Exception e){ throw new IOException(e); }
}
+
private void resetAndSkip(long blockSum) throws IOException{
try{
- decryptor.reset();
- decryptor.skipNext(blockSum); // recalculate
- }
- catch (Exception e){
- throw new IOException(e);
+ decryptor.resetAndSkip(blockSum);
}
+ catch (Exception e){ throw new IOException(e); }
}
+
private byte[] readChunk(int bytes) throws IOException{
byte[] chunkBytes = new byte[bytes];
long actuallyRead = super.read(chunkBytes, 0, bytes);
if (actuallyRead != bytes)
- throw new IOException("Can't read. " + actuallyRead + "/"+ bytes);
+ throw new IOException("Can't read. "+ bytes +"/" + actuallyRead);
return chunkBytes;
}
private boolean isPointerInsideEncryptedSection(){
- return (pseudoPos-pointerInsideDecryptedSection >= mediaOffsetPositionStart) &&
- (pseudoPos-pointerInsideDecryptedSection < mediaOffsetPositionEnd);
+ return (pseudoPos-pointerInsideDecryptedSection >= encryptedStartOffset) &&
+ (pseudoPos-pointerInsideDecryptedSection < encryptedEndOffset);
}
private boolean isEndPositionInsideEncryptedSection(long requestedBytesCount){
- return ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) >= mediaOffsetPositionStart) &&
- ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) < mediaOffsetPositionEnd);
+ return ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) >= encryptedStartOffset) &&
+ ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) < encryptedEndOffset);
}
@Override
@@ -175,7 +204,7 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
if (isEndPositionInsideEncryptedSection(n)){ // If we need to move somewhere out of the encrypted section
log.trace("4.1. Pointer Inside + End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+n)+")");
- long blocksToSkipCountingFromStart = (pseudoPos+n - mediaOffsetPositionStart) / 0x200; // always positive
+ long blocksToSkipCountingFromStart = (pseudoPos+n - encryptedStartOffset) / 0x200; // always positive
resetAndSkip(blocksToSkipCountingFromStart);
long leftovers = realCountOfBytesToSkip % 0x200; // most likely will be 0; TODO: a lot of tests
@@ -197,7 +226,7 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
if (isEndPositionInsideEncryptedSection(n)) { //pointer will be inside Encrypted Section, but now outside
log.trace("5. End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+n)+")");
//skip to start if the block we need
- long bytesToSkipTillEncryptedBlock = mediaOffsetPositionStart - pseudoPos;
+ long bytesToSkipTillEncryptedBlock = encryptedStartOffset - pseudoPos;
long blocksToSkipCountingFromStart = (n - bytesToSkipTillEncryptedBlock) / 0x200; // always positive
long bytesToSkipTillRequiredBlock = bytesToSkipTillEncryptedBlock + blocksToSkipCountingFromStart * 0x200;
long leftovers = n - bytesToSkipTillRequiredBlock; // most likely will be 0;
@@ -230,6 +259,7 @@ public class AesCtrBufferedInputStream extends BufferedInputStream {
log.trace("Skip loop: skipped: "+skipped+"\tmustSkip "+mustSkip);
}
}
+
@Override
public synchronized int read() throws IOException {
byte[] b = new byte[1];
diff --git a/src/main/java/libKonogonka/aesctr/AesCtrDecrypt.java b/src/main/java/libKonogonka/aesctr/AesCtrDecrypt.java
new file mode 100644
index 0000000..78f86b9
--- /dev/null
+++ b/src/main/java/libKonogonka/aesctr/AesCtrDecrypt.java
@@ -0,0 +1,32 @@
+package libKonogonka.aesctr;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import java.security.Security;
+
+public abstract class AesCtrDecrypt {
+ private static boolean shouldBeInitialized = true;
+
+ protected AesCtrDecrypt(){
+ if (shouldBeInitialized){
+ Security.addProvider(new BouncyCastleProvider());
+ shouldBeInitialized = false;
+ }
+ }
+
+ /**
+ * Decrypts next block of bytes. Usually 0x200.
+ * @param encryptedBlock Encrypted bytes
+ * @return Decrypted bytes
+ */
+ abstract public byte[] decryptNext(byte[] encryptedBlock);
+ /**
+ * Initializes cipher again using updated IV (CTR)
+ * @param blockCount - how many blockCount from encrypted section start should be skipped. Block size = 0x200
+ * */
+ abstract public void resetAndSkip(long blockCount) throws Exception;
+ /**
+ * Initializes cipher again using initial IV (CTR)
+ * */
+ abstract public void reset() throws Exception;
+}
diff --git a/src/main/java/libKonogonka/ctraesclassic/AesCtrDecryptClassic.java b/src/main/java/libKonogonka/aesctr/AesCtrDecryptClassic.java
similarity index 60%
rename from src/main/java/libKonogonka/ctraesclassic/AesCtrDecryptClassic.java
rename to src/main/java/libKonogonka/aesctr/AesCtrDecryptClassic.java
index d0d9372..d8ebeca 100644
--- a/src/main/java/libKonogonka/ctraesclassic/AesCtrDecryptClassic.java
+++ b/src/main/java/libKonogonka/aesctr/AesCtrDecryptClassic.java
@@ -16,51 +16,35 @@
You should have received a copy of the GNU General Public License
along with libKonogonka. If not, see .
*/
-package libKonogonka.ctraesclassic;
+package libKonogonka.aesctr;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import libKonogonka.Converter;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.nio.ByteBuffer;
-import java.security.Security;
-
-public class AesCtrDecryptClassic {
-
- private static boolean BCinitialized = false;
-
- private void initBCProvider(){
- Security.addProvider(new BouncyCastleProvider());
- BCinitialized = true;
- }
+public class AesCtrDecryptClassic extends AesCtrDecrypt {
private final SecretKeySpec key;
private final byte[] ivArray;
private Cipher cipher;
public AesCtrDecryptClassic(String keyString, byte[] ivArray) throws Exception{
- if ( ! BCinitialized)
- initBCProvider();
- byte[] keyArray = hexStrToByteArray(keyString);
+ super();
+ this.key = new SecretKeySpec(Converter.hexStringToByteArray(keyString), "AES");
this.ivArray = ivArray;
- key = new SecretKeySpec(keyArray, "AES");
- cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
- IvParameterSpec iv = new IvParameterSpec(ivArray.clone());
- cipher.init(Cipher.DECRYPT_MODE, key, iv);
+ reset();
}
-
+ @Override
public byte[] decryptNext(byte[] encryptedData) {
return cipher.update(encryptedData);
}
- /**
- * Initializes cipher again using updated IV
- * @param blocks - how many blocks from encrypted section start should be skipped. Block size = 0x200
- * */
- public void resetAndSkip(long blocks) throws Exception{
- reset(calculateCtr(blocks * 0x200));
+ @Override
+ public void resetAndSkip(long blockCount) throws Exception{
+ reset(calculateCtr(blockCount * 0x200));
}
private byte[] calculateCtr(long offset){
BigInteger ctr = new BigInteger(ivArray);
@@ -75,9 +59,7 @@ public class AesCtrDecryptClassic {
return ctrCalculated;
}
- /**
- * Initializes cipher again using initial IV
- * */
+ @Override
public void reset() throws Exception{
reset(ivArray.clone());
}
@@ -87,14 +69,4 @@ public class AesCtrDecryptClassic {
IvParameterSpec iv = new IvParameterSpec(updatedIvArray);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
}
-
- private byte[] hexStrToByteArray(String s) {
- int len = s.length();
- byte[] data = new byte[len / 2];
- for (int i = 0; i < len; i += 2) {
- data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
- + Character.digit(s.charAt(i+1), 16));
- }
- return data;
- }
}
diff --git a/src/main/java/libKonogonka/aesctr/AesCtrDecryptForMediaBlocks.java b/src/main/java/libKonogonka/aesctr/AesCtrDecryptForMediaBlocks.java
new file mode 100644
index 0000000..4eac17e
--- /dev/null
+++ b/src/main/java/libKonogonka/aesctr/AesCtrDecryptForMediaBlocks.java
@@ -0,0 +1,66 @@
+/*
+ Copyright 2019-2022 Dmitry Isaenko
+
+ This file is part of libKonogonka.
+
+ libKonogonka is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ libKonogonka is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with libKonogonka. If not, see .
+*/
+package libKonogonka.aesctr;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Arrays;
+
+/**
+ * Simplify decryption for NCA's AES CTR sections
+ */
+public class AesCtrDecryptForMediaBlocks extends AesCtrDecrypt {
+ private final SecretKeySpec key;
+ private final byte[] ivArray;
+ private Cipher cipher;
+
+ private final long initialOffset;
+
+ public AesCtrDecryptForMediaBlocks(byte[] key, byte[] sectionCTR, long realMediaOffset) throws Exception{
+ super();
+ this.key = new SecretKeySpec(key, "AES");
+ this.ivArray = Arrays.copyOf(sectionCTR, 0x10); // IV for CTR == 16 bytes; Populate first 4 bytes taken from Header's section Block CTR (aka SecureValue)
+ this.initialOffset = realMediaOffset;
+ reset();
+ }
+ @Override
+ public byte[] decryptNext(byte[] encryptedBlock){
+ return cipher.update(encryptedBlock);
+ }
+ @Override
+ public void resetAndSkip(long blockCount) throws Exception{
+ cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
+ long mediaOffset = initialOffset + (blockCount * 0x200L);
+ cipher.init(Cipher.DECRYPT_MODE, key, getIv(mediaOffset));
+ }
+ private IvParameterSpec getIv(long mediaOffset){ // Populate last 8 bytes calculated. Thanks hactool!
+ byte[] iv = ivArray.clone();
+ long offset = mediaOffset >> 4;
+ for (int i = 0; i < 8; i++){
+ iv[0x10-i-1] = (byte)(offset & 0xff);
+ offset >>= 8;
+ }
+ return new IvParameterSpec(iv);
+ }
+ @Override
+ public void reset() throws Exception{
+ resetAndSkip(0);
+ }
+}
diff --git a/src/main/java/libKonogonka/ctraesclassic/InFileStreamClassicProducer.java b/src/main/java/libKonogonka/aesctr/InFileStreamClassicProducer.java
similarity index 97%
rename from src/main/java/libKonogonka/ctraesclassic/InFileStreamClassicProducer.java
rename to src/main/java/libKonogonka/aesctr/InFileStreamClassicProducer.java
index dbe1700..5eec1ff 100644
--- a/src/main/java/libKonogonka/ctraesclassic/InFileStreamClassicProducer.java
+++ b/src/main/java/libKonogonka/aesctr/InFileStreamClassicProducer.java
@@ -16,10 +16,9 @@
You should have received a copy of the GNU General Public License
along with libKonogonka. If not, see .
*/
-package libKonogonka.ctraesclassic;
+package libKonogonka.aesctr;
import libKonogonka.IProducer;
-import libKonogonka.ctraes.InFileStreamProducer;
import java.io.BufferedInputStream;
import java.io.File;
@@ -145,7 +144,7 @@ public class InFileStreamClassicProducer implements IProducer {
else
is = Files.newInputStream(filePath);
- AesCtrClassicBufferedInputStream stream = new AesCtrClassicBufferedInputStream(
+ AesCtrBufferedInputStream stream = new AesCtrBufferedInputStream(
decryptor, encryptedStartOffset, encryptedEndOffset, is, fileSize);
if (offset != stream.skip(offset))
diff --git a/src/main/java/libKonogonka/ctraes/InFileStreamProducer.java b/src/main/java/libKonogonka/aesctr/InFileStreamProducer.java
similarity index 99%
rename from src/main/java/libKonogonka/ctraes/InFileStreamProducer.java
rename to src/main/java/libKonogonka/aesctr/InFileStreamProducer.java
index a45a03e..c52ddd1 100644
--- a/src/main/java/libKonogonka/ctraes/InFileStreamProducer.java
+++ b/src/main/java/libKonogonka/aesctr/InFileStreamProducer.java
@@ -16,7 +16,7 @@
You should have received a copy of the GNU General Public License
along with libKonogonka. If not, see .
*/
-package libKonogonka.ctraes;
+package libKonogonka.aesctr;
import libKonogonka.IProducer;
diff --git a/src/main/java/libKonogonka/ctraes/AesCtrDecryptForMediaBlocks.java b/src/main/java/libKonogonka/ctraes/AesCtrDecryptForMediaBlocks.java
deleted file mode 100644
index 46fe3ec..0000000
--- a/src/main/java/libKonogonka/ctraes/AesCtrDecryptForMediaBlocks.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- Copyright 2019-2022 Dmitry Isaenko
-
- This file is part of libKonogonka.
-
- libKonogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- libKonogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with libKonogonka. If not, see .
-*/
-package libKonogonka.ctraes;
-
-import libKonogonka.Converter;
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-import javax.crypto.Cipher;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.security.Security;
-
-/**
- * Simplify decryption of the CTR for NCA's AesCtr sections
- */
-public class AesCtrDecryptForMediaBlocks {
-
- private static boolean BCinitialized = false;
- private Cipher cipher;
- private final SecretKeySpec key;
-
- private long realMediaOffset;
- private byte[] ivArray;
-
- private final byte[] initialSectionCTR;
- private final long initialRealMediaOffset;
-
- public AesCtrDecryptForMediaBlocks(byte[] key, byte[] sectionCTR, long realMediaOffset) throws Exception{
- if ( ! BCinitialized)
- initBCProvider();
- this.key = new SecretKeySpec(key, "AES");
- this.initialSectionCTR = sectionCTR;
- this.initialRealMediaOffset = realMediaOffset;
- reset();
- }
- private void initBCProvider(){
- Security.addProvider(new BouncyCastleProvider());
- BCinitialized = true;
- }
-
- public void skipNext(){
- realMediaOffset += 0x200;
- }
-
- public void skipNext(long blocksNum){
- realMediaOffset += blocksNum * 0x200;
- }
-
- public byte[] decryptNext(byte[] encryptedBlock) throws Exception{
- updateIV();
- byte[] decryptedBlock = decrypt(encryptedBlock);
- realMediaOffset += 0x200;
- return decryptedBlock;
- }
- // Populate last 8 bytes calculated. Thanks hactool project!
- private void updateIV(){
- long offset = realMediaOffset >> 4;
- for (int i = 0; i < 0x8; i++){
- ivArray[0x10-i-1] = (byte)(offset & 0xff); // Note: issues could be here
- offset >>= 8;
- }
- }
- private byte[] decrypt(byte[] encryptedData) throws Exception{
- IvParameterSpec iv = new IvParameterSpec(ivArray);
- cipher.init(Cipher.DECRYPT_MODE, key, iv);
- return cipher.doFinal(encryptedData);
- }
-
- public void reset() throws Exception{
- realMediaOffset = initialRealMediaOffset;
- cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
- // IV for CTR == 16 bytes
- ivArray = new byte[0x10];
- // Populate first 4 bytes taken from Header's section Block CTR (aka SecureValue)
- System.arraycopy(Converter.flip(initialSectionCTR), 0x0, ivArray, 0x0, 0x8);
- }
-}
diff --git a/src/main/java/libKonogonka/ctraesclassic/AesCtrClassicBufferedInputStream.java b/src/main/java/libKonogonka/ctraesclassic/AesCtrClassicBufferedInputStream.java
deleted file mode 100644
index c0a9293..0000000
--- a/src/main/java/libKonogonka/ctraesclassic/AesCtrClassicBufferedInputStream.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- Copyright 2019-2023 Dmitry Isaenko
-
- This file is part of libKonogonka.
-
- libKonogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- libKonogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with libKonogonka. If not, see .
- */
-package libKonogonka.ctraesclassic;
-
-import libKonogonka.RainbowDump;
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
-
-import java.io.*;
-
-public class AesCtrClassicBufferedInputStream extends BufferedInputStream {
- private final static Logger log = LogManager.getLogger(AesCtrClassicBufferedInputStream.class);
-
- private final AesCtrDecryptClassic decryptor;
- private final long encryptedStartOffset;
- private final long encryptedEndOffset;
- private final long fileSize;
-
- private byte[] decryptedBytes;
- private long pseudoPos;
- private int pointerInsideDecryptedSection;
-
- public AesCtrClassicBufferedInputStream(AesCtrDecryptClassic decryptor,
- long encryptedStartOffset,
- long encryptedEndOffset,
- InputStream inputStream,
- long fileSize){
- super(inputStream, 0x200);
- this.decryptor = decryptor;
- this.encryptedStartOffset = encryptedStartOffset;
- this.encryptedEndOffset = encryptedEndOffset;
- this.fileSize = fileSize;
-
- log.trace(" EncryptedStartOffset : "+RainbowDump.formatDecHexString(encryptedStartOffset)+
- "\n EncryptedEndOffset : "+RainbowDump.formatDecHexString(encryptedEndOffset));
- }
-
- @Override
- public synchronized int read(byte[] b) throws IOException{
- int bytesToRead = b.length;
- if (isPointerInsideEncryptedSection()){
- int bytesFromFirstBlock = 0x200 - pointerInsideDecryptedSection;
- if (bytesFromFirstBlock > bytesToRead){
- log.trace("1.2. Pointer Inside + End Position Inside (Decrypted) Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- System.arraycopy(decryptedBytes, pointerInsideDecryptedSection, b, 0, bytesToRead);
-
- pseudoPos += bytesToRead;
- pointerInsideDecryptedSection += bytesToRead;
- return b.length;
- }
-
- if (isEndPositionInsideEncryptedSection(b.length)) {
- log.trace("1.1. Pointer Inside + End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- int middleBlocksCount = (bytesToRead - bytesFromFirstBlock) / 0x200;
- int bytesFromLastBlock = (bytesToRead - bytesFromFirstBlock) % 0x200;
- //1
- System.arraycopy(decryptedBytes, pointerInsideDecryptedSection, b, 0, bytesFromFirstBlock);
- //2
- for (int i = 0; i < middleBlocksCount; i++) {
- fillDecryptedCache();
- System.arraycopy(decryptedBytes, 0, b, bytesFromFirstBlock+i*0x200, 0x200);
- }
- //3
- if(fileSize > (pseudoPos+bytesToRead)) {
- fillDecryptedCache();
- System.arraycopy(decryptedBytes, 0, b, bytesFromFirstBlock + middleBlocksCount * 0x200, bytesFromLastBlock);
- }
- pseudoPos += bytesToRead;
- pointerInsideDecryptedSection = bytesFromLastBlock;
- return b.length;
- }
- log.trace("1. Pointer Inside + End Position Outside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- int middleBlocksCount = (int) ((encryptedEndOffset - (pseudoPos+bytesFromFirstBlock)) / 0x200);
- int bytesFromEnd = bytesToRead - bytesFromFirstBlock - middleBlocksCount * 0x200;
- //1
- System.arraycopy(decryptedBytes, pointerInsideDecryptedSection, b, 0, bytesFromFirstBlock);
- //2
- //log.debug("\n"+bytesFromFirstBlock+"\n"+ middleBlocksCount+" = "+(middleBlocksCount*0x200)+" bytes\n"+ bytesFromEnd+"\n");
- for (int i = 0; i < middleBlocksCount; i++) {
- fillDecryptedCache();
- System.arraycopy(decryptedBytes, 0, b, bytesFromFirstBlock+i*0x200, 0x200);
- }
- //3 // TODO: if it's zero?
- System.arraycopy(readChunk(bytesFromEnd), 0, b, bytesFromFirstBlock+middleBlocksCount*0x200, bytesFromEnd);
- pseudoPos += bytesToRead;
- pointerInsideDecryptedSection = 0;
- return b.length;
- }
- if (isEndPositionInsideEncryptedSection(bytesToRead)) {
- log.trace("2. End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- int bytesTillEncrypted = (int) (encryptedStartOffset - pseudoPos);
- int fullEncryptedBlocks = (bytesToRead - bytesTillEncrypted) / 0x200;
- int incompleteEncryptedBytes = (bytesToRead - bytesTillEncrypted) % 0x200;
- System.arraycopy(readChunk(bytesTillEncrypted), 0, b, 0, bytesTillEncrypted);
- //2
- for (int i = 0; i < fullEncryptedBlocks; i++) {
- fillDecryptedCache();
- System.arraycopy(decryptedBytes, 0, b, fullEncryptedBlocks+i*0x200, 0x200);
- }
- //3
- fillDecryptedCache();
- System.arraycopy(decryptedBytes, 0, b, bytesTillEncrypted+fullEncryptedBlocks*0x200, incompleteEncryptedBytes);
- pseudoPos += bytesToRead;
- pointerInsideDecryptedSection = incompleteEncryptedBytes;
- return b.length;
- }
- log.trace("3. Not encrypted ("+pseudoPos+"-"+(pseudoPos+b.length)+")");
- pseudoPos += bytesToRead;
- pointerInsideDecryptedSection = 0;
- return super.read(b);
- }
- private void fillDecryptedCache() throws IOException{
- try{
- decryptedBytes = decryptor.decryptNext(readChunk(0x200));
- }
- catch (Exception e){
- throw new IOException(e);
- }
- }
-
- private byte[] readChunk(int bytes) throws IOException{
- byte[] chunkBytes = new byte[bytes];
- long actuallyRead = super.read(chunkBytes);
- if (actuallyRead != bytes)
- throw new IOException("Can't read. "+ bytes +"/" + actuallyRead);
- return chunkBytes;
- }
-
- private boolean isPointerInsideEncryptedSection(){
- return (pseudoPos-pointerInsideDecryptedSection >= encryptedStartOffset) &&
- (pseudoPos-pointerInsideDecryptedSection < encryptedEndOffset);
- }
- private boolean isEndPositionInsideEncryptedSection(long requestedBytesCount){
- return ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) >= encryptedStartOffset) &&
- ((pseudoPos-pointerInsideDecryptedSection + requestedBytesCount) < encryptedEndOffset);
- }
-
- @Override
- public synchronized long skip(long n) throws IOException {
- if (isPointerInsideEncryptedSection()){
- long realCountOfBytesToSkip = n - (0x200 - pointerInsideDecryptedSection);
- if (realCountOfBytesToSkip <= 0){
- pseudoPos += n;
- pointerInsideDecryptedSection += n;
- return n;
- }
-
- if (isEndPositionInsideEncryptedSection(n)){ // If we need to move somewhere out of the encrypted section
- log.trace("4.1. Pointer Inside + End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+n)+")");
- long blocksToSkipCountingFromStart = (pseudoPos+n - encryptedStartOffset) / 0x200; // always positive
- resetAndSkip(blocksToSkipCountingFromStart);
-
- long leftovers = realCountOfBytesToSkip % 0x200; // most likely will be 0; TODO: a lot of tests
- long bytesToSkipTillRequiredBlock = realCountOfBytesToSkip - leftovers;
- skipLoop(bytesToSkipTillRequiredBlock);
- fillDecryptedCache();
- pseudoPos += n;
- pointerInsideDecryptedSection = (int) leftovers;
- return n;
- }
- log.trace("4. Pointer Inside + End Position Outside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+n)+")");
- skipLoop(realCountOfBytesToSkip);
- pseudoPos += n;
- pointerInsideDecryptedSection = 0;
- return n;
- // just fast-forward to position we need and flush caches
- }
-
- if (isEndPositionInsideEncryptedSection(n)) { //pointer will be inside Encrypted Section, but now outside
- log.trace("5. End Position Inside Encrypted Section ("+pseudoPos+"-"+(pseudoPos+n)+")");
- //skip to start if the block we need
- long bytesToSkipTillEncryptedBlock = encryptedStartOffset - pseudoPos;
- long blocksToSkipCountingFromStart = (n - bytesToSkipTillEncryptedBlock) / 0x200; // always positive
- long bytesToSkipTillRequiredBlock = bytesToSkipTillEncryptedBlock + blocksToSkipCountingFromStart * 0x200;
- long leftovers = n - bytesToSkipTillRequiredBlock; // most likely will be 0;
-
- long skipped = super.skip(bytesToSkipTillRequiredBlock);
- if (bytesToSkipTillRequiredBlock != skipped)
- throw new IOException("Can't skip bytes. To skip: " +
- bytesToSkipTillEncryptedBlock +
- ".\nActually skipped: " + skipped +
- ".\nLeftovers inside encrypted section: " + leftovers);
- log.trace("\tBlocks skipped "+blocksToSkipCountingFromStart);
- resetAndSkip(blocksToSkipCountingFromStart);
- fillDecryptedCache();
- pseudoPos += n;
- pointerInsideDecryptedSection = (int) leftovers;
- return n;
- }
- log.trace("6. Not encrypted ("+pseudoPos+"-"+(pseudoPos+n)+")");
- skipLoop(n);
- pseudoPos += n;
- pointerInsideDecryptedSection = 0;
- return n;
- }
- private void skipLoop(long size) throws IOException{
- long mustSkip = size;
- long skipped = 0;
- while (mustSkip > 0){
- skipped += super.skip(mustSkip);
- mustSkip = size - skipped;
- log.trace("Skip loop: skipped: "+skipped+"\tmustSkip "+mustSkip);
- }
- }
- private void resetAndSkip(long blockSum) throws IOException{
- try {
- decryptor.resetAndSkip(blockSum);
- }
- catch (Exception e){ throw new IOException(e); }
- }
-
- @Override
- public synchronized int read() throws IOException {
- byte[] b = new byte[1];
- if (read(b) != -1)
- return b[0];
- return -1;
- }
-
- @Override
- public boolean markSupported() {
- return false;
- }
-
- @Override
- public synchronized void mark(int readlimit) {}
-
- @Override
- public synchronized void reset() throws IOException {
- throw new IOException("Not supported");
- }
-}
\ No newline at end of file
diff --git a/src/main/java/libKonogonka/ctraesclassic/AesCtrStream.java b/src/main/java/libKonogonka/ctraesclassic/AesCtrStream.java
deleted file mode 100644
index 9c3b35e..0000000
--- a/src/main/java/libKonogonka/ctraesclassic/AesCtrStream.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- Copyright 2019-2023 Dmitry Isaenko
-
- This file is part of libKonogonka.
-
- libKonogonka is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- libKonogonka is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with libKonogonka. If not, see .
-*/
-package libKonogonka.ctraesclassic;
-
-import org.bouncycastle.jce.provider.BouncyCastleProvider;
-
-import javax.crypto.Cipher;
-import javax.crypto.CipherInputStream;
-import javax.crypto.spec.IvParameterSpec;
-import javax.crypto.spec.SecretKeySpec;
-import java.io.InputStream;
-import java.security.Security;
-
-@Deprecated
-public class AesCtrStream {
- private static boolean BCinitialized = false;
-
- private static void initBCProvider(){
- Security.addProvider(new BouncyCastleProvider());
- BCinitialized = true;
- }
- private AesCtrStream(){ }
-
- public static CipherInputStream getStream(String keyString, byte[] IVarray, InputStream inputStream) throws Exception{
- if ( ! BCinitialized)
- initBCProvider();
- byte[] keyArray = hexStrToByteArray(keyString);
- SecretKeySpec key = new SecretKeySpec(keyArray, "AES");
- Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding", "BC");
- IvParameterSpec iv = new IvParameterSpec(IVarray.clone());
- cipher.init(Cipher.DECRYPT_MODE, key, iv);
- return new CipherInputStream(inputStream, cipher);
- }
-
- private static byte[] hexStrToByteArray(String s) {
- int len = s.length();
- byte[] data = new byte[len / 2];
- for (int i = 0; i < len; i += 2) {
- data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
- + Character.digit(s.charAt(i+1), 16));
- }
- return data;
- }
-}
diff --git a/src/test/java/libKonogonka/package2/Ini1ExtractTest.java b/src/test/java/libKonogonka/package2/Ini1ExtractTest.java
index 90c1c4b..326e254 100644
--- a/src/test/java/libKonogonka/package2/Ini1ExtractTest.java
+++ b/src/test/java/libKonogonka/package2/Ini1ExtractTest.java
@@ -7,7 +7,7 @@ import libKonogonka.Tools.RomFs.FileSystemEntry;
import libKonogonka.Tools.RomFs.RomFsProvider;
import libKonogonka.Tools.other.System2.System2Provider;
import libKonogonka.Tools.other.System2.ini1.Ini1Provider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/libKonogonka/package2/KernelBinExtractTest.java b/src/test/java/libKonogonka/package2/KernelBinExtractTest.java
index 1407988..6b09c36 100644
--- a/src/test/java/libKonogonka/package2/KernelBinExtractTest.java
+++ b/src/test/java/libKonogonka/package2/KernelBinExtractTest.java
@@ -6,14 +6,13 @@ import libKonogonka.Tools.NCA.NCAProvider;
import libKonogonka.Tools.RomFs.FileSystemEntry;
import libKonogonka.Tools.RomFs.RomFsProvider;
import libKonogonka.Tools.other.System2.System2Provider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.junit.jupiter.api.*;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
diff --git a/src/test/java/libKonogonka/package2/Kip1ExtractDecompressedTest.java b/src/test/java/libKonogonka/package2/Kip1ExtractDecompressedTest.java
index 0b2b26e..dfeaeed 100644
--- a/src/test/java/libKonogonka/package2/Kip1ExtractDecompressedTest.java
+++ b/src/test/java/libKonogonka/package2/Kip1ExtractDecompressedTest.java
@@ -8,7 +8,7 @@ import libKonogonka.Tools.RomFs.RomFsProvider;
import libKonogonka.Tools.other.System2.System2Provider;
import libKonogonka.Tools.other.System2.ini1.Ini1Provider;
import libKonogonka.Tools.other.System2.ini1.KIP1Provider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/libKonogonka/package2/Kip1ExtractTest.java b/src/test/java/libKonogonka/package2/Kip1ExtractTest.java
index 2f04604..8172a63 100644
--- a/src/test/java/libKonogonka/package2/Kip1ExtractTest.java
+++ b/src/test/java/libKonogonka/package2/Kip1ExtractTest.java
@@ -8,7 +8,7 @@ import libKonogonka.Tools.RomFs.RomFsProvider;
import libKonogonka.Tools.other.System2.System2Provider;
import libKonogonka.Tools.other.System2.ini1.Ini1Provider;
import libKonogonka.Tools.other.System2.ini1.KIP1Provider;
-import libKonogonka.ctraes.InFileStreamProducer;
+import libKonogonka.aesctr.InFileStreamProducer;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/libKonogonka/unsorted/NSPpfs0EncryptedTest.java b/src/test/java/libKonogonka/unsorted/NSPpfs0EncryptedTest.java
index 527ac65..8509346 100644
--- a/src/test/java/libKonogonka/unsorted/NSPpfs0EncryptedTest.java
+++ b/src/test/java/libKonogonka/unsorted/NSPpfs0EncryptedTest.java
@@ -24,8 +24,8 @@ import libKonogonka.TitleKeyChainHolder;
import libKonogonka.Tools.NCA.NCAProvider;
import libKonogonka.Tools.PFS0.PFS0Provider;
import libKonogonka.Tools.PFS0.PFS0subFile;
-import libKonogonka.ctraes.AesCtrBufferedInputStream;
-import libKonogonka.ctraes.AesCtrDecryptForMediaBlocks;
+import libKonogonka.aesctr.AesCtrBufferedInputStream;
+import libKonogonka.aesctr.AesCtrDecryptForMediaBlocks;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
diff --git a/src/test/java/libKonogonka/unsorted/Pfs0EncryptedTest.java b/src/test/java/libKonogonka/unsorted/Pfs0EncryptedTest.java
index bf39269..d656e02 100644
--- a/src/test/java/libKonogonka/unsorted/Pfs0EncryptedTest.java
+++ b/src/test/java/libKonogonka/unsorted/Pfs0EncryptedTest.java
@@ -23,8 +23,8 @@ import libKonogonka.RainbowDump;
import libKonogonka.Tools.NCA.NCAProvider;
import libKonogonka.Tools.PFS0.PFS0Provider;
import libKonogonka.Tools.PFS0.PFS0subFile;
-import libKonogonka.ctraes.AesCtrBufferedInputStream;
-import libKonogonka.ctraes.AesCtrDecryptForMediaBlocks;
+import libKonogonka.aesctr.AesCtrBufferedInputStream;
+import libKonogonka.aesctr.AesCtrDecryptForMediaBlocks;
import org.junit.jupiter.api.*;
import java.io.*;
diff --git a/src/test/java/libKonogonka/unsorted/RomFsEncryptedTest.java b/src/test/java/libKonogonka/unsorted/RomFsEncryptedTest.java
index ebe4ece..4ef5417 100644
--- a/src/test/java/libKonogonka/unsorted/RomFsEncryptedTest.java
+++ b/src/test/java/libKonogonka/unsorted/RomFsEncryptedTest.java
@@ -18,13 +18,13 @@
*/
package libKonogonka.unsorted;
-import libKonogonka.ctraes.AesCtrBufferedInputStream;
+import libKonogonka.aesctr.AesCtrBufferedInputStream;
import libKonogonka.KeyChainHolder;
import libKonogonka.RainbowDump;
import libKonogonka.Tools.NCA.NCAProvider;
import libKonogonka.Tools.NCA.NCASectionTableBlock.NcaFsHeader;
import libKonogonka.Tools.RomFs.FileSystemEntry;
-import libKonogonka.ctraes.AesCtrDecryptForMediaBlocks;
+import libKonogonka.aesctr.AesCtrDecryptForMediaBlocks;
import org.junit.jupiter.api.*;
import java.io.*;