diff --git a/NDecrypt.N3DS/CIATool.cs b/NDecrypt.N3DS/CIATool.cs
index 9bf738a..3a326e2 100644
--- a/NDecrypt.N3DS/CIATool.cs
+++ b/NDecrypt.N3DS/CIATool.cs
@@ -150,12 +150,12 @@ namespace NDecrypt.N3DS
/// Process a single partition
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessPartition(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
bool encrypt,
Stream input,
Stream output)
@@ -164,24 +164,24 @@ namespace NDecrypt.N3DS
var tableEntry = new PartitionTableEntry();
// Determine the Keys to be used
- SetEncryptionKeys(ncchHeader, partitionIndex, encrypt);
+ SetEncryptionKeys(ncchHeader, index, encrypt);
// Process the extended header
- ProcessExtendedHeader(ncchHeader, partitionIndex, tableEntry, encrypt, input, output);
+ ProcessExtendedHeader(ncchHeader, index, tableEntry, encrypt, input, output);
// If we're encrypting, encrypt the filesystems and update the flags
if (encrypt)
{
- EncryptExeFS(ncchHeader, partitionIndex, tableEntry, input, output);
- EncryptRomFS(ncchHeader, partitionIndex, tableEntry, input, output);
- UpdateEncryptCryptoAndMasks(ncchHeader, partitionIndex, tableEntry, output);
+ EncryptExeFS(ncchHeader, index, tableEntry, input, output);
+ EncryptRomFS(ncchHeader, index, tableEntry, input, output);
+ UpdateEncryptCryptoAndMasks(ncchHeader, index, tableEntry, output);
}
// If we're decrypting, decrypt the filesystems and update the flags
else
{
- DecryptExeFS(ncchHeader, partitionIndex, tableEntry, input, output);
- DecryptRomFS(ncchHeader, partitionIndex, tableEntry, input, output);
+ DecryptExeFS(ncchHeader, index, tableEntry, input, output);
+ DecryptRomFS(ncchHeader, index, tableEntry, input, output);
UpdateDecryptCryptoAndMasks(ncchHeader, tableEntry, output);
}
}
@@ -190,9 +190,9 @@ namespace NDecrypt.N3DS
/// Determine the set of keys to be used for encryption or decryption
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
- private void SetEncryptionKeys(NCCHHeader ncchHeader, int partitionIndex, bool encrypt)
+ private void SetEncryptionKeys(NCCHHeader ncchHeader, int index, bool encrypt)
{
// Get partition-specific values
byte[]? rsaSignature = ncchHeader.RSA2048Signature;
@@ -214,20 +214,20 @@ namespace NDecrypt.N3DS
}
// Get the partition keys
- KeysMap[partitionIndex] = new PartitionKeys(_decryptArgs, rsaSignature, masks, method, _development);
+ KeysMap[index] = new PartitionKeys(_decryptArgs, rsaSignature, masks, method, _development);
}
///
/// Process the extended header, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private bool ProcessExtendedHeader(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
bool encrypt,
Stream input,
@@ -241,16 +241,16 @@ namespace NDecrypt.N3DS
input.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
output.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
- Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
+ Console.WriteLine($"Partition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, ncchHeader.PlainIV(), encrypt);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey2C, ncchHeader.PlainIV(), encrypt);
output.Write(cipher.ProcessBytes(input.ReadBytes(Constants.CXTExtendedDataHeaderLength)));
output.Flush();
return true;
}
else
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Extended Header... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Extended Header... Skipping...");
return false;
}
}
@@ -259,13 +259,13 @@ namespace NDecrypt.N3DS
/// Process the extended header, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessExeFSFileEntries(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
bool encrypt,
Stream input,
@@ -280,7 +280,7 @@ namespace NDecrypt.N3DS
// If the header failed to read, log and return
if (exefsHeader?.FileHeaders == null)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS header could not be read. Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS header could not be read. Skipping...");
return;
}
@@ -296,8 +296,8 @@ namespace NDecrypt.N3DS
byte[] exefsIVWithOffsetForHeader = AddToByteArray(ncchHeader.ExeFSIV(), (int)ctroffset);
- var firstCipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, exefsIVWithOffsetForHeader, encrypt);
- var secondCipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, exefsIVWithOffsetForHeader, !encrypt);
+ var firstCipher = CreateAESCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader, encrypt);
+ var secondCipher = CreateAESCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader, !encrypt);
input.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
output.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
@@ -308,7 +308,7 @@ namespace NDecrypt.N3DS
{
output.Write(secondCipher.ProcessBytes(firstCipher.ProcessBytes(input.ReadBytes(1024 * 1024))));
output.Flush();
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
}
}
@@ -318,7 +318,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
}
}
@@ -326,13 +326,13 @@ namespace NDecrypt.N3DS
/// Process the ExeFS Filename Table
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessExeFSFilenameTable(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
bool encrypt,
Stream input,
@@ -344,9 +344,9 @@ namespace NDecrypt.N3DS
input.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
output.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
- Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
+ Console.WriteLine($"Partition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
- var exeFSFilenameTable = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, ncchHeader.ExeFSIV(), encrypt);
+ var exeFSFilenameTable = CreateAESCipher(KeysMap[index].NormalKey2C, ncchHeader.ExeFSIV(), encrypt);
output.Write(exeFSFilenameTable.ProcessBytes(input.ReadBytes((int)mediaUnitSize)));
output.Flush();
}
@@ -355,13 +355,13 @@ namespace NDecrypt.N3DS
/// Process the ExeFS, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessExeFS(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
bool encrypt,
Stream input,
@@ -376,7 +376,7 @@ namespace NDecrypt.N3DS
byte[] exefsIVWithOffset = AddToByteArray(ncchHeader.ExeFSIV(), ctroffsetE);
- var exeFS = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, exefsIVWithOffset, encrypt);
+ var exeFS = CreateAESCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset, encrypt);
input.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
output.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
@@ -386,7 +386,7 @@ namespace NDecrypt.N3DS
{
output.Write(exeFS.ProcessBytes(input.ReadBytes(1024 * 1024)));
output.Flush();
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
}
}
if (exefsSizeB > 0)
@@ -395,7 +395,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
}
#endregion
@@ -406,12 +406,12 @@ namespace NDecrypt.N3DS
/// Decrypt the ExeFS, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Stream representing the input
/// Stream representing the output
private void DecryptExeFS(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
Stream input,
Stream output)
@@ -419,32 +419,32 @@ namespace NDecrypt.N3DS
// If the ExeFS size is 0, we log and return
if (ncchHeader.ExeFSSizeInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return;
}
// Decrypt the filename table
- ProcessExeFSFilenameTable(ncchHeader, partitionIndex, tableEntry, encrypt: false, input, output);
+ ProcessExeFSFilenameTable(ncchHeader, index, tableEntry, encrypt: false, input, output);
// For all but the original crypto method, process each of the files in the table
if (ncchHeader.Flags!.CryptoMethod != CryptoMethod.Original)
- ProcessExeFSFileEntries(ncchHeader, partitionIndex, tableEntry, encrypt: false, input, output);
+ ProcessExeFSFileEntries(ncchHeader, index, tableEntry, encrypt: false, input, output);
// Decrypt the rest of the ExeFS
- ProcessExeFS(ncchHeader, partitionIndex, tableEntry, encrypt: false, input, output);
+ ProcessExeFS(ncchHeader, index, tableEntry, encrypt: false, input, output);
}
///
/// Decrypt the RomFS, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Stream representing the input
/// Stream representing the output
/// TODO: See how much can be extracted into a common method with Encrypt
private void DecryptRomFS(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
Stream input,
Stream output)
@@ -455,14 +455,14 @@ namespace NDecrypt.N3DS
// If the RomFS offset is 0, we log and return
if (ncchHeader.RomFSOffsetInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} RomFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return;
}
long romfsSizeM = (int)((long)(ncchHeader.RomFSSizeInMediaUnits * mediaUnitSize) / (1024 * 1024));
int romfsSizeB = (int)((long)(ncchHeader.RomFSSizeInMediaUnits * mediaUnitSize) % (1024 * 1024));
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, ncchHeader.RomFSIV(), encrypt: false);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey, ncchHeader.RomFSIV(), encrypt: false);
input.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
output.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
@@ -472,7 +472,7 @@ namespace NDecrypt.N3DS
{
output.Write(cipher.ProcessBytes(input.ReadBytes(1024 * 1024)));
output.Flush();
- Console.Write($"\rPartition {partitionIndex} RomFS: Decrypting: {i} / {romfsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} RomFS: Decrypting: {i} / {romfsSizeM + 1} mb");
}
}
if (romfsSizeB > 0)
@@ -481,7 +481,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} RomFS: Decrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} RomFS: Decrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
}
///
@@ -519,12 +519,12 @@ namespace NDecrypt.N3DS
/// Encrypt the ExeFS, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Stream representing the input
/// Stream representing the output
private void EncryptExeFS(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
Stream input,
Stream output)
@@ -532,7 +532,7 @@ namespace NDecrypt.N3DS
// If the ExeFS size is 0, we log and return
if (ncchHeader.ExeFSSizeInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return;
}
@@ -542,23 +542,23 @@ namespace NDecrypt.N3DS
// ProcessExeFSFileEntries(ncchHeader, reader, writer);
// Encrypt the filename table
- ProcessExeFSFilenameTable(ncchHeader, partitionIndex, tableEntry, encrypt: true, input, output);
+ ProcessExeFSFilenameTable(ncchHeader, index, tableEntry, encrypt: true, input, output);
// Encrypt the rest of the ExeFS
- ProcessExeFS(ncchHeader, partitionIndex, tableEntry, encrypt: true, input, output);
+ ProcessExeFS(ncchHeader, index, tableEntry, encrypt: true, input, output);
}
///
/// Encrypt the RomFS, if it exists
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Stream representing the input
/// Stream representing the output
/// TODO: See how much can be extracted into a common method with Decrypt
private void EncryptRomFS(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
Stream input,
Stream output)
@@ -569,7 +569,7 @@ namespace NDecrypt.N3DS
// If the RomFS offset is 0, we log and return
if (ncchHeader.RomFSOffsetInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} RomFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return;
}
@@ -577,7 +577,7 @@ namespace NDecrypt.N3DS
int romfsSizeB = (int)((long)(ncchHeader.RomFSSizeInMediaUnits * mediaUnitSize) % (1024 * 1024));
// Encrypting RomFS for partitions 1 and up always use Key0x2C
- if (partitionIndex > 0)
+ if (index > 0)
{
// TODO: Determine how to figure out the original crypto method, if possible
//if (ciaHeader.BackupHeader.Flags?.BitMasks.HasFlag(BitMasks.FixedCryptoKey) == true) // except if using zero-key
@@ -586,12 +586,12 @@ namespace NDecrypt.N3DS
//}
//else
//{
- KeysMap[partitionIndex].KeyX = (_development ? _decryptArgs.DevKeyX0x2C : _decryptArgs.KeyX0x2C);
- KeysMap[partitionIndex].NormalKey = RotateLeft((RotateLeft(KeysMap[partitionIndex].KeyX, 2, 128) ^ KeysMap[partitionIndex].KeyY) + _decryptArgs.AESHardwareConstant, 87, 128);
+ KeysMap[index].KeyX = (_development ? _decryptArgs.DevKeyX0x2C : _decryptArgs.KeyX0x2C);
+ KeysMap[index].NormalKey = RotateLeft((RotateLeft(KeysMap[index].KeyX, 2, 128) ^ KeysMap[index].KeyY) + _decryptArgs.AESHardwareConstant, 87, 128);
//}
}
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, ncchHeader.RomFSIV(), encrypt: true);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey, ncchHeader.RomFSIV(), encrypt: true);
input.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
output.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
@@ -601,7 +601,7 @@ namespace NDecrypt.N3DS
{
output.Write(cipher.ProcessBytes(input.ReadBytes(1024 * 1024)));
output.Flush();
- Console.Write($"\rPartition {partitionIndex} RomFS: Encrypting: {i} / {romfsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} RomFS: Encrypting: {i} / {romfsSizeM + 1} mb");
}
}
if (romfsSizeB > 0)
@@ -610,18 +610,18 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} RomFS: Encrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} RomFS: Encrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
}
///
/// Update the CryptoMethod and BitMasks for the encrypted partition
///
/// NCCH header representing the partition
- /// Index of the partition
+ /// Index of the partition
/// PartitionTableEntry header representing the partition
/// Stream representing the output
private void UpdateEncryptCryptoAndMasks(NCCHHeader ncchHeader,
- int partitionIndex,
+ int index,
PartitionTableEntry tableEntry,
Stream output)
{
@@ -632,7 +632,7 @@ namespace NDecrypt.N3DS
output.Seek((tableEntry.Offset * mediaUnitSize) + 0x18B, SeekOrigin.Begin);
// For partitions 1 and up, set crypto-method to 0x00
- if (partitionIndex > 0)
+ if (index > 0)
output.Write((byte)CryptoMethod.Original);
// TODO: Determine how to figure out the original crypto method, if possible
diff --git a/NDecrypt.N3DS/ThreeDSTool.cs b/NDecrypt.N3DS/ThreeDSTool.cs
index e8cd6a2..f6ffcc6 100644
--- a/NDecrypt.N3DS/ThreeDSTool.cs
+++ b/NDecrypt.N3DS/ThreeDSTool.cs
@@ -182,12 +182,12 @@ namespace NDecrypt.N3DS
/// Determine the set of keys to be used for encryption or decryption
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
- private void SetEncryptionKeys(Cart cart, int partitionIndex, bool encrypt)
+ private void SetEncryptionKeys(Cart cart, int index, bool encrypt)
{
// Get the partition
- var partition = cart.Partitions?[partitionIndex];
+ var partition = cart.Partitions?[index];
if (partition == null)
return;
@@ -210,37 +210,37 @@ namespace NDecrypt.N3DS
}
// Get the partition keys
- KeysMap[partitionIndex] = new PartitionKeys(_decryptArgs, rsaSignature, masks, method, _development);
+ KeysMap[index] = new PartitionKeys(_decryptArgs, rsaSignature, masks, method, _development);
}
///
/// Process the extended header, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private bool ProcessExtendedHeader(Cart cart,
- int partitionIndex,
+ int index,
bool encrypt,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
uint partitionOffset = partitionOffsetMU * cart.MediaUnitSize();
- if (cart.Partitions![partitionIndex]!.ExtendedHeaderSizeInBytes > 0)
+ if (cart.Partitions![index]!.ExtendedHeaderSizeInBytes > 0)
{
// Seek to the extended header
input.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
output.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
- Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
+ Console.WriteLine($"Partition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
// Create the Plain AES cipher for this partition
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, cart.PlainIV(partitionIndex), encrypt);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey2C, cart.PlainIV(index), encrypt);
// Process the extended header
byte[] readBytes = input.ReadBytes(Constants.CXTExtendedDataHeaderLength);
@@ -256,7 +256,7 @@ namespace NDecrypt.N3DS
}
else
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Extended Header... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Extended Header... Skipping...");
return false;
}
}
@@ -265,19 +265,19 @@ namespace NDecrypt.N3DS
/// Process the extended header, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessExeFSFileEntries(Cart cart,
- int partitionIndex,
+ int index,
bool encrypt,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
- uint exeFsOffsetMU = cart.Partitions![partitionIndex]!.ExeFSOffsetInMediaUnits;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
+ uint exeFsOffsetMU = cart.Partitions![index]!.ExeFSOffsetInMediaUnits;
uint exeFsHeaderOffset = (partitionOffsetMU + exeFsOffsetMU) * cart.MediaUnitSize();
uint exeFsOffset = (partitionOffsetMU + exeFsOffsetMU + 1) * cart.MediaUnitSize();
@@ -287,7 +287,7 @@ namespace NDecrypt.N3DS
// If the header failed to read, log and return
if (exefsHeader == null)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS header could not be read. Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS header could not be read. Skipping...");
return;
}
@@ -303,9 +303,9 @@ namespace NDecrypt.N3DS
uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize()) / 0x10;
// Create the ExeFS AES ciphers for this partition
- byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(partitionIndex), (int)ctroffset);
- var firstCipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, exefsIVWithOffsetForHeader, encrypt);
- var secondCipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, exefsIVWithOffsetForHeader, !encrypt);
+ byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(index), (int)ctroffset);
+ var firstCipher = CreateAESCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader, encrypt);
+ var secondCipher = CreateAESCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader, !encrypt);
// Seek to the file entry
input.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
@@ -321,7 +321,7 @@ namespace NDecrypt.N3DS
byte[] secondProcessedBytes = secondCipher.ProcessBytes(firstProcessedBytes);
output.Write(secondProcessedBytes);
output.Flush();
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
}
}
@@ -335,7 +335,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
}
}
@@ -343,29 +343,29 @@ namespace NDecrypt.N3DS
/// Process the ExeFS Filename Table
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private void ProcessExeFSFilenameTable(Cart cart,
- int partitionIndex,
+ int index,
bool encrypt,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
- uint exeFsOffsetMU = cart.Partitions![partitionIndex]!.ExeFSOffsetInMediaUnits;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
+ uint exeFsOffsetMU = cart.Partitions![index]!.ExeFSOffsetInMediaUnits;
uint exeFsHeaderOffset = (partitionOffsetMU + exeFsOffsetMU) * cart.MediaUnitSize();
// Seek to the ExeFS header
input.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
output.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
- Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
+ Console.WriteLine($"Partition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
// Create the ExeFS AES cipher for this partition
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, cart.ExeFSIV(partitionIndex), encrypt);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey2C, cart.ExeFSIV(index), encrypt);
// Process the filename table
byte[] readBytes = input.ReadBytes((int)cart.MediaUnitSize());
@@ -383,37 +383,37 @@ namespace NDecrypt.N3DS
/// Process the ExeFS, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Indicates if the file should be encrypted or decrypted
/// Stream representing the input
/// Stream representing the output
private bool ProcessExeFS(Cart cart,
- int partitionIndex,
+ int index,
bool encrypt,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
- uint exeFsOffsetMU = cart.Partitions![partitionIndex]!.ExeFSOffsetInMediaUnits;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
+ uint exeFsOffsetMU = cart.Partitions![index]!.ExeFSOffsetInMediaUnits;
uint exeFsOffset = (partitionOffsetMU + exeFsOffsetMU + 1) * cart.MediaUnitSize();
// If the RomFS offset is 0, we log and return
if (exeFsOffsetMU == 0)
{
- Console.WriteLine($"Partition {partitionIndex} RomFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return false;
}
// Get MiB-aligned block count and extra byte count
- uint exeFsSize = (cart.Partitions![partitionIndex]!.ExeFSSizeInMediaUnits - 1) * cart.MediaUnitSize();
+ uint exeFsSize = (cart.Partitions![index]!.ExeFSSizeInMediaUnits - 1) * cart.MediaUnitSize();
int exefsSizeM = (int)((long)exeFsSize / (1024 * 1024));
int exefsSizeB = (int)((long)exeFsSize % (1024 * 1024));
int ctroffsetE = (int)(cart.MediaUnitSize() / 0x10);
// Create the ExeFS AES cipher for this partition
- byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(partitionIndex), ctroffsetE);
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey2C, exefsIVWithOffset, encrypt);
+ byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(index), ctroffsetE);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset, encrypt);
// Seek to the ExeFS
input.Seek(exeFsOffset, SeekOrigin.Begin);
@@ -428,7 +428,7 @@ namespace NDecrypt.N3DS
byte[] processedBytes = cipher.ProcessBytes(readBytes);
output.Write(processedBytes);
output.Flush();
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
}
}
@@ -441,7 +441,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
return true;
}
@@ -453,64 +453,64 @@ namespace NDecrypt.N3DS
/// Decrypt the ExeFS, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the input
/// Stream representing the output
private void DecryptExeFS(Cart cart,
- int partitionIndex,
+ int index,
Stream input,
Stream output)
{
// If the ExeFS size is 0, we log and return
- if (cart.Partitions![partitionIndex]!.ExeFSSizeInMediaUnits == 0)
+ if (cart.Partitions![index]!.ExeFSSizeInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return;
}
// Decrypt the filename table
- ProcessExeFSFilenameTable(cart, partitionIndex, encrypt: false, input, output);
+ ProcessExeFSFilenameTable(cart, index, encrypt: false, input, output);
// For all but the original crypto method, process each of the files in the table
- if (cart.Partitions![partitionIndex]!.Flags!.CryptoMethod != CryptoMethod.Original)
- ProcessExeFSFileEntries(cart, partitionIndex, encrypt: false, input, output);
+ if (cart.Partitions![index]!.Flags!.CryptoMethod != CryptoMethod.Original)
+ ProcessExeFSFileEntries(cart, index, encrypt: false, input, output);
// Decrypt the rest of the ExeFS
- ProcessExeFS(cart, partitionIndex, encrypt: false, input, output);
+ ProcessExeFS(cart, index, encrypt: false, input, output);
}
///
/// Decrypt the RomFS, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the input
/// Stream representing the output
/// TODO: See how much can be extracted into a common method with Encrypt
private bool DecryptRomFS(Cart cart,
- int partitionIndex,
+ int index,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
- uint romFsOffsetMU = cart.Partitions![partitionIndex]!.RomFSOffsetInMediaUnits;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
+ uint romFsOffsetMU = cart.Partitions![index]!.RomFSOffsetInMediaUnits;
uint romFsOffset = (partitionOffsetMU + romFsOffsetMU) * cart.MediaUnitSize();
// If the RomFS offset is 0, we log and return
if (romFsOffsetMU == 0)
{
- Console.WriteLine($"Partition {partitionIndex} RomFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return false;
}
// Get MiB-aligned block count and extra byte count
- uint romFsSize = cart.Partitions![partitionIndex]!.RomFSSizeInMediaUnits * cart.MediaUnitSize();
+ uint romFsSize = cart.Partitions![index]!.RomFSSizeInMediaUnits * cart.MediaUnitSize();
long romfsSizeM = (int)((long)romFsSize / (1024 * 1024));
int romfsSizeB = (int)((long)romFsSize % (1024 * 1024));
// Create the RomFS AES cipher for this partition
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, cart.RomFSIV(partitionIndex), encrypt: false);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey, cart.RomFSIV(index), encrypt: false);
// Seek to the RomFS
input.Seek(romFsOffset, SeekOrigin.Begin);
@@ -525,7 +525,7 @@ namespace NDecrypt.N3DS
byte[] processedBytes = cipher.ProcessBytes(readBytes);
output.Write(processedBytes);
output.Flush();
- Console.Write($"\rPartition {partitionIndex} RomFS: Decrypting: {i} / {romfsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} RomFS: Decrypting: {i} / {romfsSizeM + 1} mb");
}
}
@@ -538,7 +538,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} RomFS: Decrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} RomFS: Decrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
return true;
}
@@ -546,12 +546,12 @@ namespace NDecrypt.N3DS
/// Update the CryptoMethod and BitMasks for the decrypted partition
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the output
- private static void UpdateDecryptCryptoAndMasks(Cart cart, int partitionIndex, Stream output)
+ private static void UpdateDecryptCryptoAndMasks(Cart cart, int index, Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
uint partitionOffset = partitionOffsetMU * cart.MediaUnitSize();
// Seek to the CryptoMethod location
@@ -565,7 +565,7 @@ namespace NDecrypt.N3DS
output.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
// Write the new BitMasks flag
- BitMasks flag = cart.Partitions![partitionIndex]!.Flags!.BitMasks;
+ BitMasks flag = cart.Partitions![index]!.Flags!.BitMasks;
flag &= (BitMasks)((byte)(BitMasks.FixedCryptoKey | BitMasks.NewKeyYGenerator) ^ 0xFF);
flag |= BitMasks.NoCrypto;
output.Write((byte)flag);
@@ -580,18 +580,18 @@ namespace NDecrypt.N3DS
/// Encrypt the ExeFS, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the input
/// Stream representing the output
private void EncryptExeFS(Cart cart,
- int partitionIndex,
+ int index,
Stream input,
Stream output)
{
// If the ExeFS size is 0, we log and return
- if (cart.Partitions![partitionIndex]!.ExeFSSizeInMediaUnits == 0)
+ if (cart.Partitions![index]!.ExeFSSizeInMediaUnits == 0)
{
- Console.WriteLine($"Partition {partitionIndex} ExeFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} ExeFS: No Data... Skipping...");
return;
}
@@ -600,31 +600,31 @@ namespace NDecrypt.N3DS
// For all but the original crypto method, process each of the files in the table
if (backupHeader!.Flags!.CryptoMethod != CryptoMethod.Original)
- ProcessExeFSFileEntries(cart, partitionIndex, encrypt: true, input, output);
+ ProcessExeFSFileEntries(cart, index, encrypt: true, input, output);
// Encrypt the filename table
- ProcessExeFSFilenameTable(cart, partitionIndex, encrypt: true, input, output);
+ ProcessExeFSFilenameTable(cart, index, encrypt: true, input, output);
// Encrypt the rest of the ExeFS
- ProcessExeFS(cart, partitionIndex, encrypt: true, input, output);
+ ProcessExeFS(cart, index, encrypt: true, input, output);
}
///
/// Encrypt the RomFS, if it exists
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the input
/// Stream representing the output
/// TODO: See how much can be extracted into a common method with Decrypt
private bool EncryptRomFS(Cart cart,
- int partitionIndex,
+ int index,
Stream input,
Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
- uint romFsOffsetMU = cart.Partitions![partitionIndex]!.RomFSOffsetInMediaUnits;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
+ uint romFsOffsetMU = cart.Partitions![index]!.RomFSOffsetInMediaUnits;
uint romFsOffset = (partitionOffsetMU + romFsOffsetMU) * cart.MediaUnitSize();
// Get the backup header
@@ -633,32 +633,32 @@ namespace NDecrypt.N3DS
// If the RomFS offset is 0, we log and return
if (romFsOffsetMU == 0)
{
- Console.WriteLine($"Partition {partitionIndex} RomFS: No Data... Skipping...");
+ Console.WriteLine($"Partition {index} RomFS: No Data... Skipping...");
return false;
}
// Get MiB-aligned block count and extra byte count
- uint romFsSize = cart.Partitions![partitionIndex]!.RomFSSizeInMediaUnits * cart.MediaUnitSize();
+ uint romFsSize = cart.Partitions![index]!.RomFSSizeInMediaUnits * cart.MediaUnitSize();
long romfsSizeM = (int)((long)romFsSize / (1024 * 1024));
int romfsSizeB = (int)((long)romFsSize % (1024 * 1024));
// Encrypting RomFS for partitions 1 and up always use Key0x2C
- if (partitionIndex > 0)
+ if (index > 0)
{
// Except if using zero-key
if (backupHeader!.Flags!.BitMasks.HasFlag(BitMasks.FixedCryptoKey))
{
- KeysMap[partitionIndex].NormalKey = 0x00;
+ KeysMap[index].NormalKey = 0x00;
}
else
{
- KeysMap[partitionIndex].KeyX = (_development ? _decryptArgs.DevKeyX0x2C : _decryptArgs.KeyX0x2C);
- KeysMap[partitionIndex].NormalKey = RotateLeft((RotateLeft(KeysMap[partitionIndex].KeyX, 2, 128) ^ KeysMap[partitionIndex].KeyY) + _decryptArgs.AESHardwareConstant, 87, 128);
+ KeysMap[index].KeyX = (_development ? _decryptArgs.DevKeyX0x2C : _decryptArgs.KeyX0x2C);
+ KeysMap[index].NormalKey = RotateLeft((RotateLeft(KeysMap[index].KeyX, 2, 128) ^ KeysMap[index].KeyY) + _decryptArgs.AESHardwareConstant, 87, 128);
}
}
// Create the RomFS AES cipher for this partition
- var cipher = CreateAESCipher(KeysMap[partitionIndex].NormalKey, cart.RomFSIV(partitionIndex), encrypt: true);
+ var cipher = CreateAESCipher(KeysMap[index].NormalKey, cart.RomFSIV(index), encrypt: true);
// Seek to the RomFS
input.Seek(romFsOffset, SeekOrigin.Begin);
@@ -673,7 +673,7 @@ namespace NDecrypt.N3DS
byte[] processedBytes = cipher.ProcessBytes(readBytes);
output.Write(processedBytes);
output.Flush();
- Console.Write($"\rPartition {partitionIndex} RomFS: Encrypting: {i} / {romfsSizeM + 1} mb");
+ Console.Write($"\rPartition {index} RomFS: Encrypting: {i} / {romfsSizeM + 1} mb");
}
}
@@ -686,7 +686,7 @@ namespace NDecrypt.N3DS
output.Flush();
}
- Console.Write($"\rPartition {partitionIndex} RomFS: Encrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
+ Console.Write($"\rPartition {index} RomFS: Encrypting: {romfsSizeM + 1} / {romfsSizeM + 1} mb... Done!\r\n");
return true;
}
@@ -694,12 +694,12 @@ namespace NDecrypt.N3DS
/// Update the CryptoMethod and BitMasks for the encrypted partition
///
/// Cart representing the 3DS file
- /// Index of the partition
+ /// Index of the partition
/// Stream representing the output
- private static void UpdateEncryptCryptoAndMasks(Cart cart, int partitionIndex, Stream output)
+ private static void UpdateEncryptCryptoAndMasks(Cart cart, int index, Stream output)
{
// Get required offsets
- uint partitionOffsetMU = cart.Header!.PartitionsTable![partitionIndex]!.Offset;
+ uint partitionOffsetMU = cart.Header!.PartitionsTable![index]!.Offset;
uint partitionOffset = partitionOffsetMU * cart.MediaUnitSize();
// Get the backup header
@@ -711,7 +711,7 @@ namespace NDecrypt.N3DS
// Write the new CryptoMethod
// - For partitions 1 and up, set crypto-method to 0x00
// - If partition 0, restore crypto-method from backup flags
- byte cryptoMethod = partitionIndex > 0 ? (byte)CryptoMethod.Original : (byte)backupHeader!.Flags!.CryptoMethod;
+ byte cryptoMethod = index > 0 ? (byte)CryptoMethod.Original : (byte)backupHeader!.Flags!.CryptoMethod;
output.Write(cryptoMethod);
output.Flush();
@@ -719,7 +719,7 @@ namespace NDecrypt.N3DS
output.Seek(partitionOffset + 0x18F, SeekOrigin.Begin);
// Write the new BitMasks flag
- BitMasks flag = cart.Partitions![partitionIndex]!.Flags!.BitMasks;
+ BitMasks flag = cart.Partitions![index]!.Flags!.BitMasks;
flag &= (BitMasks.FixedCryptoKey | BitMasks.NewKeyYGenerator | BitMasks.NoCrypto) ^ (BitMasks)0xFF;
flag |= (BitMasks.FixedCryptoKey | BitMasks.NewKeyYGenerator) & backupHeader!.Flags!.BitMasks;
output.Write((byte)flag);