Add byte array helpers

This commit is contained in:
Matt Nadareski
2024-11-13 14:41:32 -05:00
parent 7a5593dd72
commit 41293ab7c5
4 changed files with 114 additions and 10 deletions

View File

@@ -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);

View File

@@ -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
/// <param name="input">Byte array to add to</param>
/// <param name="add">Amount to add</param>
/// <returns>Byte array representing the new value</returns>
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;
}
/// <summary>
/// Add two numbers represented by byte arrays
/// </summary>
/// <param name="left">Byte array to add to</param>
/// <param name="right">Amount to add</param>
/// <returns>Byte array representing the new value</returns>
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;
}
/// <summary>
/// Perform a rotate left on a BigInteger
/// </summary>
@@ -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)));
}
/// <summary>
/// Perform a rotate left on a byte array
/// </summary>
/// <param name="val">Byte array value to rotate</param>
/// <param name="r_bits">Number of bits to rotate</param>
/// <returns>Rotated byte array value</returns>
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;
}
/// <summary>
/// XOR two numbers represented by byte arrays
/// </summary>
/// <param name="left">Byte array to XOR to</param>
/// <param name="right">Amount to XOR</param>
/// <returns>Byte array representing the new value</returns>
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

View File

@@ -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);

View File

@@ -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");