diff --git a/NDecrypt.Core/DSTool.cs b/NDecrypt.Core/DSTool.cs
index 3850468..0898494 100644
--- a/NDecrypt.Core/DSTool.cs
+++ b/NDecrypt.Core/DSTool.cs
@@ -2,20 +2,12 @@
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
-using SabreTools.Models.Nitro;
-using SabreTools.Serialization.Deserializers;
+using SabreTools.Serialization.Wrappers;
namespace NDecrypt.Core
{
public class DSTool : ITool
{
- #region Encryption process variables
-
- private uint[] _cardHash = new uint[0x412];
- private uint[] _arg2 = new uint[3];
-
- #endregion
-
///
/// Decryption args to use while processing
///
@@ -35,22 +27,31 @@ namespace NDecrypt.Core
{
// Open the read and write on the same file for inplace processing
using var reader = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
// Deserialize the cart information
- var commonHeader = Nitro.ParseCommonHeader(reader);
- if (commonHeader == null)
+ var nitro = Nitro.Create(reader);
+ if (nitro == null)
{
Console.WriteLine("Error: Not a DS or DSi Rom!");
return false;
}
- // Reset state variables
- _cardHash = new uint[0x412];
- _arg2 = new uint[3];
+ // Ensure the secure area was read
+ if (nitro.SecureArea == null)
+ {
+ Console.WriteLine("Error: Invalid secure area!");
+ return false;
+ }
// Encrypt the secure area
- EncryptSecureArea(commonHeader, force, reader, writer);
+ nitro.EncryptSecureArea(_decryptArgs.NitroEncryptionData, force);
+
+ // Write the encrypted secure area
+ using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
+ writer.Seek(0x4000, SeekOrigin.Begin);
+ writer.Write(nitro.SecureArea);
+ writer.Flush();
+
return true;
}
catch
@@ -61,123 +62,6 @@ namespace NDecrypt.Core
}
}
- ///
- /// Encrypt secure area in the DS/DSi file
- /// s
- /// CommonHeader representing the DS file header
- /// Indicates if the operation should be forced
- /// Stream representing the input
- /// Stream representing the output
- private void EncryptSecureArea(CommonHeader commonHeader, bool force, Stream reader, Stream writer)
- {
- // If we're forcing the operation, tell the user
- if (force)
- {
- Console.WriteLine("File is not verified due to force flag being set.");
- }
- // If we're not forcing the operation, check to see if we should be proceeding
- else
- {
- bool? isDecrypted = CheckIfDecrypted(reader);
- if (isDecrypted == null)
- {
- Console.WriteLine("File has an empty secure area, cannot proceed");
- return;
- }
- else if (!isDecrypted.Value)
- {
- Console.WriteLine("File is already encrypted");
- return;
- }
- }
-
- EncryptARM9(commonHeader, reader, writer);
- Console.WriteLine("File has been encrypted");
- }
-
- ///
- /// Encrypt the secure ARM9 region of the file, if possible
- ///
- /// CommonHeader representing the DS header
- /// Indicates if the file should be encrypted or decrypted
- /// Stream representing the input
- /// Stream representing the output
- private void EncryptARM9(CommonHeader commonHeader, Stream reader, Stream writer)
- {
- // Seek to the beginning of the secure area
- reader.Seek(0x4000, SeekOrigin.Begin);
- writer.Seek(0x4000, SeekOrigin.Begin);
-
- // Grab the first two blocks
- uint p0 = reader.ReadUInt32();
- uint p1 = reader.ReadUInt32();
-
- // Perform the initialization steps
- Init1(commonHeader);
- _arg2[1] <<= 1;
- _arg2[2] >>= 1;
- Init2();
-
- // Ensure alignment
- reader.Seek(0x4008, SeekOrigin.Begin);
- writer.Seek(0x4008, SeekOrigin.Begin);
-
- // Loop throgh the main encryption step
- uint size = 0x800 - 8;
- while (size > 0)
- {
- p0 = reader.ReadUInt32();
- p1 = reader.ReadUInt32();
-
- Encrypt(ref p1, ref p0);
-
- writer.Write(p0);
- writer.Write(p1);
-
- size -= 8;
- }
-
- // Replace the header explicitly
- reader.Seek(0x4000, SeekOrigin.Begin);
- writer.Seek(0x4000, SeekOrigin.Begin);
-
- p0 = reader.ReadUInt32();
- p1 = reader.ReadUInt32();
-
- if (p0 == 0xE7FFDEFF && p1 == 0xE7FFDEFF)
- {
- p0 = Constants.MAGIC30;
- p1 = Constants.MAGIC34;
- }
-
- Encrypt(ref p1, ref p0);
- Init1(commonHeader);
- Encrypt(ref p1, ref p0);
-
- writer.Write(p0);
- writer.Write(p1);
- }
-
- ///
- /// Perform an encryption step
- ///
- /// First unsigned value to use in encryption
- /// Second unsigned value to use in encryption
- private void Encrypt(ref uint arg1, ref uint arg2)
- {
- uint a = arg1;
- uint b = arg2;
- for (int i = 0; i < 16; i++)
- {
- uint c = _cardHash[i] ^ a;
- a = b ^ Lookup(c);
- b = c;
- }
-
- arg2 = a ^ _cardHash[16];
- arg1 = b ^ _cardHash[17];
- }
-
#endregion
#region Decrypt
@@ -189,22 +73,30 @@ namespace NDecrypt.Core
{
// Open the read and write on the same file for inplace processing
using var reader = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
- using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
// Deserialize the cart information
- var commonHeader = Nitro.ParseCommonHeader(reader);
- if (commonHeader == null)
+ var nitro = Nitro.Create(reader);
+ if (nitro == null)
{
Console.WriteLine("Error: Not a DS or DSi Rom!");
return false;
}
- // Reset state variables
- _cardHash = new uint[0x412];
- _arg2 = new uint[3];
+ // Ensure the secure area was read
+ if (nitro.SecureArea == null)
+ {
+ Console.WriteLine("Error: Invalid secure area!");
+ return false;
+ }
// Decrypt the secure area
- DecryptSecureArea(commonHeader, force, reader, writer);
+ nitro.DecryptSecureArea(_decryptArgs.NitroEncryptionData, force);
+
+ // Write the decrypted secure area
+ using var writer = File.Open(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
+ writer.Seek(0x4000, SeekOrigin.Begin);
+ writer.Write(nitro.SecureArea);
+ writer.Flush();
return true;
}
@@ -216,115 +108,6 @@ namespace NDecrypt.Core
}
}
- ///
- /// Decrypt secure area in the DS/DSi file
- /// s
- /// CommonHeader representing the DS file header
- /// Indicates if the operation should be forced
- /// Stream representing the input
- /// Stream representing the output
- private void DecryptSecureArea(CommonHeader commonHeader, bool force, Stream reader, Stream writer)
- {
- // If we're forcing the operation, tell the user
- if (force)
- {
- Console.WriteLine("File is not verified due to force flag being set.");
- }
- // If we're not forcing the operation, check to see if we should be proceeding
- else
- {
- bool? isDecrypted = CheckIfDecrypted(reader);
- if (isDecrypted == null)
- {
- Console.WriteLine("File has an empty secure area, cannot proceed");
- return;
- }
- else if (isDecrypted.Value)
- {
- Console.WriteLine("File is already decrypted");
- return;
- }
- }
-
- DecryptARM9(commonHeader, reader, writer);
- Console.WriteLine("File has been decrypted");
- }
-
- ///
- /// Decrypt the secure ARM9 region of the file, if possible
- ///
- /// CommonHeader representing the DS header
- /// Indicates if the file should be encrypted or decrypted
- /// Stream representing the input
- /// Stream representing the output
- private void DecryptARM9(CommonHeader commonHeader, Stream reader, Stream writer)
- {
- // Seek to the beginning of the secure area
- reader.Seek(0x4000, SeekOrigin.Begin);
- writer.Seek(0x4000, SeekOrigin.Begin);
-
- // Grab the first two blocks
- uint p0 = reader.ReadUInt32();
- uint p1 = reader.ReadUInt32();
-
- // Perform the initialization steps
- Init1(commonHeader);
- Decrypt(ref p1, ref p0);
- _arg2[1] <<= 1;
- _arg2[2] >>= 1;
- Init2();
-
- // Set the proper flags
- Decrypt(ref p1, ref p0);
- if (p0 == Constants.MAGIC30 && p1 == Constants.MAGIC34)
- {
- p0 = 0xE7FFDEFF;
- p1 = 0xE7FFDEFF;
- }
-
- writer.Write(p0);
- writer.Write(p1);
-
- // Ensure alignment
- reader.Seek(0x4008, SeekOrigin.Begin);
- writer.Seek(0x4008, SeekOrigin.Begin);
-
- // Loop throgh the main encryption step
- uint size = 0x800 - 8;
- while (size > 0)
- {
- p0 = reader.ReadUInt32();
- p1 = reader.ReadUInt32();
-
- Decrypt(ref p1, ref p0);
-
- writer.Write(p0);
- writer.Write(p1);
-
- size -= 8;
- }
- }
-
- ///
- /// Perform a decryption step
- ///
- /// First unsigned value to use in decryption
- /// Second unsigned value to use in decryption
- private void Decrypt(ref uint arg1, ref uint arg2)
- {
- uint a = arg1;
- uint b = arg2;
- for (int i = 17; i > 1; i--)
- {
- uint c = _cardHash[i] ^ a;
- a = b ^ Lookup(c);
- b = c;
- }
-
- arg1 = b ^ _cardHash[0];
- arg2 = a ^ _cardHash[1];
- }
-
#endregion
#region Info
@@ -361,10 +144,6 @@ namespace NDecrypt.Core
}
}
- #endregion
-
- #region Common
-
///
/// Determine if the current file is already decrypted or not (or has an empty secure area)
///
@@ -456,87 +235,6 @@ namespace NDecrypt.Core
return firstValue == 0xE7FFDEFF && secondValue == 0xE7FFDEFF;
}
- ///
- /// First common initialization step
- ///
- /// CommonHeader representing the DS file
- private void Init1(CommonHeader commonHeader)
- {
- Buffer.BlockCopy(_decryptArgs.NitroEncryptionData, 0, _cardHash, 0, 4 * (1024 + 18));
- _arg2 = [commonHeader.GameCode, commonHeader.GameCode >> 1, commonHeader.GameCode << 1];
- Init2();
- Init2();
- }
-
- ///
- /// Second common initialization step
- ///
- private void Init2()
- {
- Encrypt(ref _arg2[2], ref _arg2[1]);
- Encrypt(ref _arg2[1], ref _arg2[0]);
-
- byte[] allBytes =[.. BitConverter.GetBytes(_arg2[0]),
- .. BitConverter.GetBytes(_arg2[1]),
- .. BitConverter.GetBytes(_arg2[2])];
-
- UpdateHashtable(allBytes);
- }
-
- ///
- /// Lookup the value from the hashtable
- ///
- /// Value to lookup in the hashtable
- /// Processed value through the hashtable
- private uint Lookup(uint v)
- {
- uint a = (v >> 24) & 0xFF;
- uint b = (v >> 16) & 0xFF;
- uint c = (v >> 8) & 0xFF;
- uint d = (v >> 0) & 0xFF;
-
- a = _cardHash[a + 18 + 0];
- b = _cardHash[b + 18 + 256];
- c = _cardHash[c + 18 + 512];
- d = _cardHash[d + 18 + 768];
-
- return d + (c ^ (b + a));
- }
-
- ///
- /// Update the hashtable
- ///
- /// Value to update the hashtable with
- private void UpdateHashtable(byte[] arg1)
- {
- for (int j = 0; j < 18; j++)
- {
- uint r3 = 0;
- for (int i = 0; i < 4; i++)
- {
- r3 <<= 8;
- r3 |= arg1[(j * 4 + i) & 7];
- }
-
- _cardHash[j] ^= r3;
- }
-
- uint tmp1 = 0;
- uint tmp2 = 0;
- for (int i = 0; i < 18; i += 2)
- {
- Encrypt(ref tmp1, ref tmp2);
- _cardHash[i + 0] = tmp1;
- _cardHash[i + 1] = tmp2;
- }
- for (int i = 0; i < 0x400; i += 2)
- {
- Encrypt(ref tmp1, ref tmp2);
- _cardHash[i + 18 + 0] = tmp1;
- _cardHash[i + 18 + 1] = tmp2;
- }
- }
-
#endregion
}
}