mirror of
https://github.com/SabreTools/NDecrypt.git
synced 2026-07-08 18:06:38 +00:00
Move encrypt flag out of args
This commit is contained in:
@@ -10,11 +10,6 @@ namespace NDecrypt.Core
|
||||
{
|
||||
#region Common Fields
|
||||
|
||||
/// <summary>
|
||||
/// Flag to indicate operation
|
||||
/// </summary>
|
||||
public bool Encrypt { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Flag to indicate forcing the operation
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
{
|
||||
public interface ITool
|
||||
{
|
||||
bool ProcessFile();
|
||||
/// <summary>
|
||||
/// Attempts to encrypt an input file
|
||||
/// </summary>
|
||||
/// <returns>True if the file could be encrypted, false otherwise</returns>
|
||||
bool EncryptFile();
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to decrypt an input file
|
||||
/// </summary>
|
||||
/// <returns>True if the file could be decrypted, false otherwise</returns>
|
||||
bool DecryptFile();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,10 +57,17 @@ namespace NDecrypt.N3DS
|
||||
|
||||
#region Common Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool EncryptFile() => ProcessFile(encrypt: true);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool DecryptFile() => ProcessFile(encrypt: false);
|
||||
|
||||
/// <summary>
|
||||
/// Process an input file given the input values
|
||||
/// </summary>
|
||||
public bool ProcessFile()
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
private bool ProcessFile(bool encrypt)
|
||||
{
|
||||
// Ensure the constants are all set
|
||||
if (decryptArgs.IsReady != true)
|
||||
@@ -84,7 +91,7 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
// Process all NCCH partitions
|
||||
ProcessAllPartitions(cia, reader, writer);
|
||||
ProcessAllPartitions(cia, encrypt, reader, writer);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -100,9 +107,10 @@ namespace NDecrypt.N3DS
|
||||
/// Process all partitions in the content file data of a CIA header
|
||||
/// </summary>
|
||||
/// <param name="cia">CIA representing the 3DS CIA file</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessAllPartitions(CIA cia, Stream reader, Stream writer)
|
||||
private void ProcessAllPartitions(CIA cia, bool encrypt, Stream reader, Stream writer)
|
||||
{
|
||||
// Iterate over all NCCH partitions
|
||||
for (int p = 0; p < cia.Partitions!.Length; p++)
|
||||
@@ -111,19 +119,21 @@ namespace NDecrypt.N3DS
|
||||
if (ncchHeader == null)
|
||||
continue;
|
||||
|
||||
ProcessPartition(p, ncchHeader, reader, writer);
|
||||
ProcessPartition(ncchHeader, p, encrypt, reader, writer);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process a single partition
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessPartition(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void ProcessPartition(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -133,9 +143,9 @@ namespace NDecrypt.N3DS
|
||||
Console.WriteLine($"Partition {partitionIndex} is not verified due to force flag being set.");
|
||||
}
|
||||
// If we're not forcing the operation, check if the 'NoCrypto' bit is set
|
||||
else if (ncchHeader.Flags!.PossblyDecrypted() ^ decryptArgs.Encrypt)
|
||||
else if (ncchHeader.Flags!.PossblyDecrypted() ^ encrypt)
|
||||
{
|
||||
Console.WriteLine($"Partition {partitionIndex}: Already " + (decryptArgs.Encrypt ? "Encrypted" : "Decrypted") + "?...");
|
||||
Console.WriteLine($"Partition {partitionIndex}: Already " + (encrypt ? "Encrypted" : "Decrypted") + "?...");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -143,24 +153,24 @@ namespace NDecrypt.N3DS
|
||||
var tableEntry = new PartitionTableEntry();
|
||||
|
||||
// Determine the Keys to be used
|
||||
SetEncryptionKeys(partitionIndex, ncchHeader);
|
||||
SetEncryptionKeys(ncchHeader, partitionIndex, encrypt);
|
||||
|
||||
// Process the extended header
|
||||
ProcessExtendedHeader(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExtendedHeader(ncchHeader, partitionIndex, tableEntry, encrypt, reader, writer);
|
||||
|
||||
// If we're encrypting, encrypt the filesystems and update the flags
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
{
|
||||
EncryptExeFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
EncryptRomFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
UpdateEncryptCryptoAndMasks(partitionIndex, ncchHeader, tableEntry, writer);
|
||||
EncryptExeFS(ncchHeader, partitionIndex, tableEntry, reader, writer);
|
||||
EncryptRomFS(ncchHeader, partitionIndex, tableEntry, reader, writer);
|
||||
UpdateEncryptCryptoAndMasks(ncchHeader, partitionIndex, tableEntry, writer);
|
||||
}
|
||||
|
||||
// If we're decrypting, decrypt the filesystems and update the flags
|
||||
else
|
||||
{
|
||||
DecryptExeFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
DecryptRomFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
DecryptExeFS(ncchHeader, partitionIndex, tableEntry, reader, writer);
|
||||
DecryptRomFS(ncchHeader, partitionIndex, tableEntry, reader, writer);
|
||||
UpdateDecryptCryptoAndMasks(ncchHeader, tableEntry, writer);
|
||||
}
|
||||
}
|
||||
@@ -168,9 +178,10 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Determine the set of keys to be used for encryption or decryption
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
private void SetEncryptionKeys(int partitionIndex, NCCHHeader ncchHeader)
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
private void SetEncryptionKeys(NCCHHeader ncchHeader, int partitionIndex, bool encrypt)
|
||||
{
|
||||
KeyX[partitionIndex] = 0;
|
||||
KeyX2C[partitionIndex] = decryptArgs.Development ? decryptArgs.DevKeyX0x2C : decryptArgs.KeyX0x2C;
|
||||
@@ -188,7 +199,7 @@ namespace NDecrypt.N3DS
|
||||
// Set the header to use based on mode
|
||||
BitMasks masks = BitMasks.NoCrypto;
|
||||
CryptoMethod method = CryptoMethod.Original;
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
{
|
||||
// TODO: Can we actually re-encrypt a CIA?
|
||||
//masks = ciaHeader.BackupHeader.Flags.BitMasks;
|
||||
@@ -236,14 +247,16 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Process the extended header, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExtendedHeader(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private bool ProcessExtendedHeader(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -255,9 +268,9 @@ namespace NDecrypt.N3DS
|
||||
reader.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset * mediaUnitSize) + 0x200, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], ncchHeader.PlainIV(), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], ncchHeader.PlainIV(), encrypt);
|
||||
writer.Write(cipher.ProcessBytes(reader.ReadBytes(Constants.CXTExtendedDataHeaderLength)));
|
||||
writer.Flush();
|
||||
return true;
|
||||
@@ -272,14 +285,16 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Process the extended header, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFileEntries(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void ProcessExeFSFileEntries(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -308,8 +323,8 @@ namespace NDecrypt.N3DS
|
||||
|
||||
byte[] exefsIVWithOffsetForHeader = AddToByteArray(ncchHeader.ExeFSIV(), (int)ctroffset);
|
||||
|
||||
var firstCipher = CreateAESCipher(NormalKey[partitionIndex], exefsIVWithOffsetForHeader, decryptArgs.Encrypt);
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !decryptArgs.Encrypt);
|
||||
var firstCipher = CreateAESCipher(NormalKey[partitionIndex], exefsIVWithOffsetForHeader, encrypt);
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !encrypt);
|
||||
|
||||
reader.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.Seek((((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) + 1) * mediaUnitSize) + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
@@ -320,7 +335,7 @@ namespace NDecrypt.N3DS
|
||||
{
|
||||
writer.Write(secondCipher.ProcessBytes(firstCipher.ProcessBytes(reader.ReadBytes(1024 * 1024))));
|
||||
writer.Flush();
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -330,21 +345,23 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Process the ExeFS Filename Table
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFilenameTable(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void ProcessExeFSFilenameTable(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -354,9 +371,9 @@ namespace NDecrypt.N3DS
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
|
||||
var exeFSFilenameTable = CreateAESCipher(NormalKey2C[partitionIndex], ncchHeader.ExeFSIV(), decryptArgs.Encrypt);
|
||||
var exeFSFilenameTable = CreateAESCipher(NormalKey2C[partitionIndex], ncchHeader.ExeFSIV(), encrypt);
|
||||
writer.Write(exeFSFilenameTable.ProcessBytes(reader.ReadBytes((int)mediaUnitSize)));
|
||||
writer.Flush();
|
||||
}
|
||||
@@ -364,14 +381,16 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Process the ExeFS, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void ProcessExeFS(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -384,7 +403,7 @@ namespace NDecrypt.N3DS
|
||||
|
||||
byte[] exefsIVWithOffset = AddToByteArray(ncchHeader.ExeFSIV(), ctroffsetE);
|
||||
|
||||
var exeFS = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, decryptArgs.Encrypt);
|
||||
var exeFS = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, encrypt);
|
||||
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.ExeFSOffsetInMediaUnits + 1) * mediaUnitSize, SeekOrigin.Begin);
|
||||
@@ -394,7 +413,7 @@ namespace NDecrypt.N3DS
|
||||
{
|
||||
writer.Write(exeFS.ProcessBytes(reader.ReadBytes(1024 * 1024)));
|
||||
writer.Flush();
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
|
||||
}
|
||||
}
|
||||
if (exefsSizeB > 0)
|
||||
@@ -403,7 +422,7 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -413,13 +432,13 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Decrypt the ExeFS, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void DecryptExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void DecryptExeFS(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
@@ -432,27 +451,27 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
// Decrypt the filename table
|
||||
ProcessExeFSFilenameTable(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExeFSFilenameTable(ncchHeader, partitionIndex, tableEntry, encrypt: false, reader, writer);
|
||||
|
||||
// For all but the original crypto method, process each of the files in the table
|
||||
if (ncchHeader.Flags!.CryptoMethod != CryptoMethod.Original)
|
||||
ProcessExeFSFileEntries(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExeFSFileEntries(ncchHeader, partitionIndex, tableEntry, encrypt: false, reader, writer);
|
||||
|
||||
// Decrypt the rest of the ExeFS
|
||||
ProcessExeFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExeFS(ncchHeader, partitionIndex, tableEntry, encrypt: false, reader, writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypt the RomFS, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Encrypt
|
||||
private void DecryptRomFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void DecryptRomFS(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
@@ -470,7 +489,7 @@ namespace NDecrypt.N3DS
|
||||
long romfsSizeM = (int)((long)(ncchHeader.RomFSSizeInMediaUnits * mediaUnitSize) / (1024 * 1024));
|
||||
int romfsSizeB = (int)((long)(ncchHeader.RomFSSizeInMediaUnits * mediaUnitSize) % (1024 * 1024));
|
||||
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), encrypt: false);
|
||||
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
@@ -526,13 +545,13 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Encrypt the ExeFS, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void EncryptExeFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void EncryptExeFS(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
@@ -550,23 +569,23 @@ namespace NDecrypt.N3DS
|
||||
// ProcessExeFSFileEntries(ncchHeader, reader, writer);
|
||||
|
||||
// Encrypt the filename table
|
||||
ProcessExeFSFilenameTable(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExeFSFilenameTable(ncchHeader, partitionIndex, tableEntry, encrypt: true, reader, writer);
|
||||
|
||||
// Encrypt the rest of the ExeFS
|
||||
ProcessExeFS(partitionIndex, ncchHeader, tableEntry, reader, writer);
|
||||
ProcessExeFS(ncchHeader, partitionIndex, tableEntry, encrypt: true, reader, writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encrypt the RomFS, if it exists
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
/// TODO: See how much can be extracted into a common method with Decrypt
|
||||
private void EncryptRomFS(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void EncryptRomFS(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
@@ -599,7 +618,7 @@ namespace NDecrypt.N3DS
|
||||
//}
|
||||
}
|
||||
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], ncchHeader.RomFSIV(), encrypt: true);
|
||||
|
||||
reader.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
writer.Seek((tableEntry.Offset + ncchHeader.RomFSOffsetInMediaUnits) * mediaUnitSize, SeekOrigin.Begin);
|
||||
@@ -624,12 +643,12 @@ namespace NDecrypt.N3DS
|
||||
/// <summary>
|
||||
/// Update the CryptoMethod and BitMasks for the encrypted partition
|
||||
/// </summary>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="ncchHeader">NCCH header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void UpdateEncryptCryptoAndMasks(int partitionIndex,
|
||||
NCCHHeader ncchHeader,
|
||||
private void UpdateEncryptCryptoAndMasks(NCCHHeader ncchHeader,
|
||||
int partitionIndex,
|
||||
PartitionTableEntry tableEntry,
|
||||
Stream writer)
|
||||
{
|
||||
|
||||
@@ -55,10 +55,17 @@ namespace NDecrypt.N3DS
|
||||
|
||||
#region Common Methods
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool EncryptFile() => ProcessFile(encrypt: true);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool DecryptFile() => ProcessFile(encrypt: false);
|
||||
|
||||
/// <summary>
|
||||
/// Process an input file given the input values
|
||||
/// </summary>
|
||||
public bool ProcessFile()
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
private bool ProcessFile(bool encrypt)
|
||||
{
|
||||
// Ensure the constants are all set
|
||||
if (decryptArgs.IsReady != true)
|
||||
@@ -82,7 +89,7 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
// Process all 8 NCCH partitions
|
||||
ProcessAllPartitions(cart, reader, writer);
|
||||
ProcessAllPartitions(cart, encrypt, reader, writer);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -98,9 +105,10 @@ namespace NDecrypt.N3DS
|
||||
/// Process all partitions in the partition table of an NCSD header
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessAllPartitions(Cart cart, Stream reader, Stream writer)
|
||||
private void ProcessAllPartitions(Cart cart, bool encrypt, Stream reader, Stream writer)
|
||||
{
|
||||
// Check the partitions table
|
||||
if (cart.Header?.PartitionsTable == null)
|
||||
@@ -119,7 +127,7 @@ namespace NDecrypt.N3DS
|
||||
continue;
|
||||
}
|
||||
|
||||
ProcessPartition(cart, partitionIndex, reader, writer);
|
||||
ProcessPartition(cart, partitionIndex, encrypt, reader, writer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,10 +136,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessPartition(Cart cart,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -141,20 +151,20 @@ namespace NDecrypt.N3DS
|
||||
Console.WriteLine($"Partition {partitionIndex} is not verified due to force flag being set.");
|
||||
}
|
||||
// If we're not forcing the operation, check if the 'NoCrypto' bit is set
|
||||
else if (cart.Partitions![partitionIndex]!.Flags!.PossblyDecrypted() ^ decryptArgs.Encrypt)
|
||||
else if (cart.Partitions![partitionIndex]!.Flags!.PossblyDecrypted() ^ encrypt)
|
||||
{
|
||||
Console.WriteLine($"Partition {partitionIndex}: Already " + (decryptArgs.Encrypt ? "Encrypted" : "Decrypted") + "?...");
|
||||
Console.WriteLine($"Partition {partitionIndex}: Already " + (encrypt ? "Encrypted" : "Decrypted") + "?...");
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the Keys to be used
|
||||
SetEncryptionKeys(cart, partitionIndex);
|
||||
SetEncryptionKeys(cart, partitionIndex, encrypt);
|
||||
|
||||
// Process the extended header
|
||||
ProcessExtendedHeader(cart, partitionIndex, reader, writer);
|
||||
ProcessExtendedHeader(cart, partitionIndex, encrypt, reader, writer);
|
||||
|
||||
// If we're encrypting, encrypt the filesystems and update the flags
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
{
|
||||
EncryptExeFS(cart, partitionIndex, reader, writer);
|
||||
EncryptRomFS(cart, partitionIndex, reader, writer);
|
||||
@@ -175,7 +185,8 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
private void SetEncryptionKeys(Cart cart, int partitionIndex)
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
private void SetEncryptionKeys(Cart cart, int partitionIndex, bool encrypt)
|
||||
{
|
||||
// Get the backup header
|
||||
var backupHeader = cart.CardInfoHeader!.InitialData!.BackupHeader;
|
||||
@@ -196,7 +207,7 @@ namespace NDecrypt.N3DS
|
||||
// Set the header to use based on mode
|
||||
BitMasks masks;
|
||||
CryptoMethod method;
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
{
|
||||
masks = backupHeader!.Flags!.BitMasks;
|
||||
method = backupHeader.Flags.CryptoMethod;
|
||||
@@ -245,10 +256,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExtendedHeader(Cart cart,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -262,10 +275,10 @@ namespace NDecrypt.N3DS
|
||||
reader.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
writer.Seek(partitionOffset + 0x200, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + ": ExHeader");
|
||||
|
||||
// Create the Plain AES cipher for this partition
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], cart.PlainIV(partitionIndex), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], cart.PlainIV(partitionIndex), encrypt);
|
||||
|
||||
// Process the extended header
|
||||
byte[] readBytes = reader.ReadBytes(Constants.CXTExtendedDataHeaderLength);
|
||||
@@ -290,11 +303,13 @@ namespace NDecrypt.N3DS
|
||||
/// Process the extended header, if it exists
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="tableEntry">PartitionTableEntry header representing the partition</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFileEntries(Cart cart,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -327,8 +342,8 @@ namespace NDecrypt.N3DS
|
||||
|
||||
// Create the ExeFS AES ciphers for this partition
|
||||
byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(partitionIndex), (int)ctroffset);
|
||||
var firstCipher = CreateAESCipher(NormalKey[partitionIndex], exefsIVWithOffsetForHeader, decryptArgs.Encrypt);
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !decryptArgs.Encrypt);
|
||||
var firstCipher = CreateAESCipher(NormalKey[partitionIndex], exefsIVWithOffsetForHeader, encrypt);
|
||||
var secondCipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffsetForHeader, !encrypt);
|
||||
|
||||
// Seek to the file entry
|
||||
reader.Seek(exeFsOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
@@ -344,7 +359,7 @@ namespace NDecrypt.N3DS
|
||||
byte[] secondProcessedBytes = secondCipher.ProcessBytes(firstProcessedBytes);
|
||||
writer.Write(secondProcessedBytes);
|
||||
writer.Flush();
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {i} / {datalenM + 1} mb...");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -358,7 +373,7 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {fileHeader.FileName}... {datalenM + 1} / {datalenM + 1} mb... Done!\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,10 +382,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessExeFSFilenameTable(Cart cart,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -383,10 +400,10 @@ namespace NDecrypt.N3DS
|
||||
reader.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsHeaderOffset, SeekOrigin.Begin);
|
||||
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
Console.WriteLine($"Partition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": ExeFS Filename Table");
|
||||
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], cart.ExeFSIV(partitionIndex), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], cart.ExeFSIV(partitionIndex), encrypt);
|
||||
|
||||
// Process the filename table
|
||||
byte[] readBytes = reader.ReadBytes((int)cart.MediaUnitSize());
|
||||
@@ -405,10 +422,12 @@ namespace NDecrypt.N3DS
|
||||
/// </summary>
|
||||
/// <param name="cart">Cart representing the 3DS file</param>
|
||||
/// <param name="partitionIndex">Index of the partition</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private bool ProcessExeFS(Cart cart,
|
||||
int partitionIndex,
|
||||
bool encrypt,
|
||||
Stream reader,
|
||||
Stream writer)
|
||||
{
|
||||
@@ -432,7 +451,7 @@ namespace NDecrypt.N3DS
|
||||
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(partitionIndex), ctroffsetE);
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey2C[partitionIndex], exefsIVWithOffset, encrypt);
|
||||
|
||||
// Seek to the ExeFS
|
||||
reader.Seek(exeFsOffset, SeekOrigin.Begin);
|
||||
@@ -447,7 +466,7 @@ namespace NDecrypt.N3DS
|
||||
byte[] processedBytes = cipher.ProcessBytes(readBytes);
|
||||
writer.Write(processedBytes);
|
||||
writer.Flush();
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {i} / {exefsSizeM + 1} mb");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +479,7 @@ namespace NDecrypt.N3DS
|
||||
writer.Flush();
|
||||
}
|
||||
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (decryptArgs.Encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
|
||||
Console.Write($"\rPartition {partitionIndex} ExeFS: " + (encrypt ? "Encrypting" : "Decrypting") + $": {exefsSizeM + 1} / {exefsSizeM + 1} mb... Done!\r\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -488,14 +507,14 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
// Decrypt the filename table
|
||||
ProcessExeFSFilenameTable(cart, partitionIndex, reader, writer);
|
||||
ProcessExeFSFilenameTable(cart, partitionIndex, encrypt: false, reader, writer);
|
||||
|
||||
// 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, reader, writer);
|
||||
ProcessExeFSFileEntries(cart, partitionIndex, encrypt: false, reader, writer);
|
||||
|
||||
// Decrypt the rest of the ExeFS
|
||||
ProcessExeFS(cart, partitionIndex, reader, writer);
|
||||
ProcessExeFS(cart, partitionIndex, encrypt: false, reader, writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -529,7 +548,7 @@ namespace NDecrypt.N3DS
|
||||
int romfsSizeB = (int)((long)romFsSize % (1024 * 1024));
|
||||
|
||||
// Create the RomFS AES cipher for this partition
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), encrypt: false);
|
||||
|
||||
// Seek to the RomFS
|
||||
reader.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
@@ -619,13 +638,13 @@ 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, reader, writer);
|
||||
ProcessExeFSFileEntries(cart, partitionIndex, encrypt: true, reader, writer);
|
||||
|
||||
// Encrypt the filename table
|
||||
ProcessExeFSFilenameTable(cart, partitionIndex, reader, writer);
|
||||
ProcessExeFSFilenameTable(cart, partitionIndex, encrypt: true, reader, writer);
|
||||
|
||||
// Encrypt the rest of the ExeFS
|
||||
ProcessExeFS(cart, partitionIndex, reader, writer);
|
||||
ProcessExeFS(cart, partitionIndex, encrypt: true, reader, writer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -677,7 +696,7 @@ namespace NDecrypt.N3DS
|
||||
}
|
||||
|
||||
// Create the RomFS AES cipher for this partition
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), decryptArgs.Encrypt);
|
||||
var cipher = CreateAESCipher(NormalKey[partitionIndex], cart.RomFSIV(partitionIndex), encrypt: true);
|
||||
|
||||
// Seek to the RomFS
|
||||
reader.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
|
||||
@@ -33,10 +33,17 @@ namespace NDecrypt.Nitro
|
||||
this.decryptArgs = decryptArgs;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool EncryptFile() => ProcessFile(encrypt: true);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public bool DecryptFile() => ProcessFile(encrypt: false);
|
||||
|
||||
/// <summary>
|
||||
/// Process an input file given the input values
|
||||
/// </summary>
|
||||
public bool ProcessFile()
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
private bool ProcessFile(bool encrypt)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -53,7 +60,7 @@ namespace NDecrypt.Nitro
|
||||
}
|
||||
|
||||
// Process the secure area
|
||||
ProcessSecureArea(cart, reader, writer);
|
||||
ProcessSecureArea(cart, encrypt, reader, writer);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -69,9 +76,10 @@ namespace NDecrypt.Nitro
|
||||
/// Process secure area in the DS/DSi file
|
||||
/// </summary>s
|
||||
/// <param name="cart">Cart representing the DS file</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessSecureArea(Cart cart, Stream reader, Stream writer)
|
||||
private void ProcessSecureArea(Cart cart, bool encrypt, Stream reader, Stream writer)
|
||||
{
|
||||
// If we're forcing the operation, tell the user
|
||||
if (decryptArgs.Force)
|
||||
@@ -87,16 +95,16 @@ namespace NDecrypt.Nitro
|
||||
Console.WriteLine("File has an empty secure area, cannot proceed");
|
||||
return;
|
||||
}
|
||||
else if (decryptArgs.Encrypt ^ isDecrypted.Value)
|
||||
else if (encrypt ^ isDecrypted.Value)
|
||||
{
|
||||
Console.WriteLine("File is already " + (decryptArgs.Encrypt ? "encrypted" : "decrypted"));
|
||||
Console.WriteLine("File is already " + (encrypt ? "encrypted" : "decrypted"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ProcessARM9(cart.CommonHeader!, reader, writer);
|
||||
ProcessARM9(cart.CommonHeader!, encrypt, reader, writer);
|
||||
|
||||
Console.WriteLine("File has been " + (decryptArgs.Encrypt ? "encrypted" : "decrypted"));
|
||||
Console.WriteLine("File has been " + (encrypt ? "encrypted" : "decrypted"));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -162,9 +170,10 @@ namespace NDecrypt.Nitro
|
||||
/// Process the secure ARM9 region of the file, if possible
|
||||
/// </summary>
|
||||
/// <param name="commonHeader">CommonHeader representing the DS header</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="reader">Stream representing the input</param>
|
||||
/// <param name="writer">Stream representing the output</param>
|
||||
private void ProcessARM9(CommonHeader commonHeader, Stream reader, Stream writer)
|
||||
private void ProcessARM9(CommonHeader commonHeader, bool encrypt, Stream reader, Stream writer)
|
||||
{
|
||||
// Seek to the beginning of the secure area
|
||||
reader.Seek(0x4000, SeekOrigin.Begin);
|
||||
@@ -176,13 +185,13 @@ namespace NDecrypt.Nitro
|
||||
|
||||
// Perform the initialization steps
|
||||
Init1(commonHeader);
|
||||
if (!decryptArgs.Encrypt) Decrypt(ref p1, ref p0);
|
||||
if (!encrypt) Decrypt(ref p1, ref p0);
|
||||
_arg2[1] <<= 1;
|
||||
_arg2[2] >>= 1;
|
||||
Init2();
|
||||
|
||||
// If we're decrypting, set the proper flags
|
||||
if (!decryptArgs.Encrypt)
|
||||
if (!encrypt)
|
||||
{
|
||||
Decrypt(ref p1, ref p0);
|
||||
if (p0 == Constants.MAGIC30 && p1 == Constants.MAGIC34)
|
||||
@@ -206,7 +215,7 @@ namespace NDecrypt.Nitro
|
||||
p0 = reader.ReadUInt32();
|
||||
p1 = reader.ReadUInt32();
|
||||
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
Encrypt(ref p1, ref p0);
|
||||
else
|
||||
Decrypt(ref p1, ref p0);
|
||||
@@ -218,7 +227,7 @@ namespace NDecrypt.Nitro
|
||||
}
|
||||
|
||||
// Replace the header explicitly if we're encrypting
|
||||
if (decryptArgs.Encrypt)
|
||||
if (encrypt)
|
||||
{
|
||||
reader.Seek(0x4000, SeekOrigin.Begin);
|
||||
writer.Seek(0x4000, SeekOrigin.Begin);
|
||||
|
||||
@@ -30,14 +30,15 @@ namespace NDecrypt
|
||||
return;
|
||||
}
|
||||
|
||||
bool encrypt;
|
||||
var decryptArgs = new DecryptArgs();
|
||||
if (args[0] == "decrypt" || args[0] == "d")
|
||||
{
|
||||
decryptArgs.Encrypt = false;
|
||||
encrypt = false;
|
||||
}
|
||||
else if (args[0] == "encrypt" || args[0] == "e")
|
||||
{
|
||||
decryptArgs.Encrypt = true;
|
||||
encrypt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -113,13 +114,13 @@ namespace NDecrypt
|
||||
{
|
||||
if (File.Exists(args[i]))
|
||||
{
|
||||
ProcessPath(args[i], decryptArgs, outputHashes);
|
||||
ProcessPath(args[i], encrypt, decryptArgs, outputHashes);
|
||||
}
|
||||
else if (Directory.Exists(args[i]))
|
||||
{
|
||||
foreach (string file in Directory.EnumerateFiles(args[i], "*", SearchOption.AllDirectories))
|
||||
{
|
||||
ProcessPath(file, decryptArgs, outputHashes);
|
||||
ProcessPath(file, encrypt, decryptArgs, outputHashes);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -133,15 +134,29 @@ namespace NDecrypt
|
||||
/// Display a basic help text
|
||||
/// </summary>
|
||||
/// <param name="path">Path to the file to process</param>
|
||||
/// <param name="encrypt">Indicates if the file should be encrypted or decrypted</param>
|
||||
/// <param name="decryptArgs">DecryptArgs to use during processing</param>
|
||||
/// <param name="outputHashes">True to write out a hashfile, false otherwise</param>
|
||||
private static void ProcessPath(string path, DecryptArgs decryptArgs, bool outputHashes)
|
||||
private static void ProcessPath(string path, bool encrypt, DecryptArgs decryptArgs, bool outputHashes)
|
||||
{
|
||||
Console.WriteLine(path);
|
||||
|
||||
ITool? tool = DeriveTool(path, decryptArgs);
|
||||
if (tool?.ProcessFile() != true)
|
||||
Console.WriteLine("Processing failed!");
|
||||
else if (outputHashes)
|
||||
if (tool == null)
|
||||
return;
|
||||
|
||||
if (encrypt && !tool.EncryptFile())
|
||||
{
|
||||
Console.WriteLine("Encryption failed!");
|
||||
return;
|
||||
}
|
||||
else if (!encrypt && !tool.DecryptFile())
|
||||
{
|
||||
Console.WriteLine("Decryption failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (outputHashes)
|
||||
WriteHashes(path);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user