diff --git a/NDecrypt.Core/CIATool.cs b/NDecrypt.Core/CIATool.cs
index a7ba60e..6cfcb36 100644
--- a/NDecrypt.Core/CIATool.cs
+++ b/NDecrypt.Core/CIATool.cs
@@ -295,7 +295,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES cipher for this partition
int ctroffsetE = (int)(mediaUnitSize / 0x10);
- byte[] exefsIVWithOffset = AddToByteArray(header.ExeFSIV(), ctroffsetE);
+ byte[] exefsIVWithOffset = Add(header.ExeFSIV(), ctroffsetE);
var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset);
// Setup and perform the decryption
@@ -393,7 +393,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES ciphers for this partition
uint ctroffset = (fileHeader.FileOffset + mediaUnitSize) / 0x10;
- byte[] exefsIVWithOffsetForHeader = AddToByteArray(header.ExeFSIV(), (int)ctroffset);
+ byte[] exefsIVWithOffsetForHeader = Add(header.ExeFSIV(), (int)ctroffset);
var firstCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader);
var secondCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
@@ -684,7 +684,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES cipher for this partition
int ctroffsetE = (int)(mediaUnitSize / 0x10);
- byte[] exefsIVWithOffset = AddToByteArray(header.ExeFSIV(), ctroffsetE);
+ byte[] exefsIVWithOffset = Add(header.ExeFSIV(), ctroffsetE);
var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset);
// Setup and perform the decryption
@@ -782,7 +782,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES ciphers for this partition
uint ctroffset = (fileHeader.FileOffset + mediaUnitSize) / 0x10;
- byte[] exefsIVWithOffsetForHeader = AddToByteArray(header.ExeFSIV(), (int)ctroffset);
+ byte[] exefsIVWithOffsetForHeader = Add(header.ExeFSIV(), (int)ctroffset);
var firstCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader);
var secondCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
diff --git a/NDecrypt.Core/CommonOperations.cs b/NDecrypt.Core/CommonOperations.cs
index 2ed107d..7845565 100644
--- a/NDecrypt.Core/CommonOperations.cs
+++ b/NDecrypt.Core/CommonOperations.cs
@@ -9,7 +9,7 @@ using SabreTools.Models.N3DS;
namespace NDecrypt.Core
{
- internal static class CommonOperations
+ public static class CommonOperations
{
#region AES
@@ -167,7 +167,7 @@ namespace NDecrypt.Core
/// Byte array to add to
/// Amount to add
/// Byte array representing the new value
- public static byte[] AddToByteArray(byte[] input, int add)
+ public static byte[] Add(byte[] input, int add)
{
int len = input.Length;
Array.Reverse(input);
@@ -190,6 +190,35 @@ namespace NDecrypt.Core
return arr;
}
+ ///
+ /// Add two numbers represented by byte arrays
+ ///
+ /// Byte array to add to
+ /// Amount to add
+ /// Byte array representing the new value
+ public static byte[] Add(byte[] left, byte[] right)
+ {
+ int addBytes = Math.Min(left.Length, right.Length);
+ int outLength = Math.Max(left.Length, right.Length);
+
+ byte[] output = new byte[outLength];
+
+ int carry = 0;
+ for (int i = 0; i < addBytes; i++)
+ {
+ int addValue = left[i] + right[i] + carry;
+ output[i] = (byte)addValue;
+ carry = addValue > byte.MaxValue ? byte.MaxValue - addValue : 0;
+ }
+
+ if (outLength != addBytes && left.Length == outLength)
+ Array.Copy(left, addBytes, output, addBytes, outLength - addBytes);
+ else if (outLength != addBytes && right.Length == outLength)
+ Array.Copy(right, addBytes, output, addBytes, outLength - addBytes);
+
+ return output;
+ }
+
///
/// Perform a rotate left on a BigInteger
///
@@ -202,6 +231,69 @@ namespace NDecrypt.Core
return (val << r_bits % max_bits) & (BigInteger.Pow(2, max_bits) - 1) | ((val & (BigInteger.Pow(2, max_bits) - 1)) >> (max_bits - (r_bits % max_bits)));
}
+ ///
+ /// Perform a rotate left on a byte array
+ ///
+ /// Byte array value to rotate
+ /// Number of bits to rotate
+ /// Rotated byte array value
+ public static byte[] RotateLeft(byte[] val, int r_bits)
+ {
+ // Shift by bytes
+ while (r_bits >= 8)
+ {
+ byte temp = val[0];
+ for (int i = 0; i < val.Length - 1; i++)
+ {
+ val[i] = val[i + 1];
+ }
+
+ val[val.Length - 1] = temp;
+ r_bits -= 8;
+ }
+
+ // Shift by bits
+ while (r_bits-- > 0)
+ {
+ int carry = 0;
+ for (int i = 0; i < val.Length; i++)
+ {
+ byte nextByte = (byte)((val[i] << 1) + carry);
+ carry = (val[i] << 1) > byte.MaxValue ? byte.MaxValue - (val[i] << 1) : 0;
+ val[i] = nextByte;
+ }
+
+ val[val.Length - 1] = (byte)(val[val.Length - 1] + carry);
+ }
+
+ return val;
+ }
+
+ ///
+ /// XOR two numbers represented by byte arrays
+ ///
+ /// Byte array to XOR to
+ /// Amount to XOR
+ /// Byte array representing the new value
+ public static byte[] Xor(byte[] left, byte[] right)
+ {
+ int xorBytes = Math.Min(left.Length, right.Length);
+ int outLength = Math.Max(left.Length, right.Length);
+
+ byte[] output = new byte[outLength];
+ for (int i = 0; i < xorBytes; i++)
+ {
+ output[i] = (byte)(left[i] ^ right[i]);
+ }
+
+ if (outLength != xorBytes && left.Length == outLength)
+ Array.Copy(left, xorBytes, output, xorBytes, outLength - xorBytes);
+ else if (outLength != xorBytes && right.Length == outLength)
+ Array.Copy(right, xorBytes, output, xorBytes, outLength - xorBytes);
+
+ return output;
+ }
+
#endregion
#region Offsets
diff --git a/NDecrypt.Core/ThreeDSTool.cs b/NDecrypt.Core/ThreeDSTool.cs
index c1b975b..fc45c06 100644
--- a/NDecrypt.Core/ThreeDSTool.cs
+++ b/NDecrypt.Core/ThreeDSTool.cs
@@ -283,7 +283,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES cipher for this partition
int ctroffsetE = (int)(cart.MediaUnitSize() / 0x10);
- byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(index), ctroffsetE);
+ byte[] exefsIVWithOffset = Add(cart.ExeFSIV(index), ctroffsetE);
var cipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset);
// Setup and perform the decryption
@@ -369,7 +369,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES ciphers for this partition
uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize()) / 0x10;
- byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(index), (int)ctroffset);
+ byte[] exefsIVWithOffsetForHeader = Add(cart.ExeFSIV(index), (int)ctroffset);
var firstCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader);
var secondCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
@@ -643,7 +643,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES cipher for this partition
int ctroffsetE = (int)(cart.MediaUnitSize() / 0x10);
- byte[] exefsIVWithOffset = AddToByteArray(cart.ExeFSIV(index), ctroffsetE);
+ byte[] exefsIVWithOffset = Add(cart.ExeFSIV(index), ctroffsetE);
var cipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffset);
// Setup and perform the encryption
@@ -729,7 +729,7 @@ namespace NDecrypt.Core
// Create the ExeFS AES ciphers for this partition
uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize()) / 0x10;
- byte[] exefsIVWithOffsetForHeader = AddToByteArray(cart.ExeFSIV(index), (int)ctroffset);
+ byte[] exefsIVWithOffsetForHeader = Add(cart.ExeFSIV(index), (int)ctroffset);
var firstCipher = CreateAESEncryptionCipher(KeysMap[index].NormalKey, exefsIVWithOffsetForHeader);
var secondCipher = CreateAESDecryptionCipher(KeysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
diff --git a/NDecrypt/Program.cs b/NDecrypt/Program.cs
index cf10c7b..b08aea7 100644
--- a/NDecrypt/Program.cs
+++ b/NDecrypt/Program.cs
@@ -14,6 +14,18 @@ namespace NDecrypt
public static void Main(string[] args)
{
+ // TEMP SHIT CODE
+
+ byte[] x =
+ [
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ ];
+ x = CommonOperations.Add(x, x);
+ string s = BitConverter.ToString(x);
+
+ // END TEMP SHIT CODE
+
if (args.Length < 2)
{
DisplayHelp("Not enough arguments");