mirror of
https://github.com/SabreTools/NDecrypt.git
synced 2026-02-04 05:35:53 +00:00
Update packages
This commit is contained in:
@@ -1,301 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Security;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace NDecrypt.Core
|
||||
{
|
||||
public static class CommonOperations
|
||||
{
|
||||
// TODO: Remove when IO updated
|
||||
#region AES
|
||||
|
||||
/// <summary>
|
||||
/// Create AES decryption cipher and intialize
|
||||
/// </summary>
|
||||
/// <param name="key">Byte array representation of 128-bit encryption key</param>
|
||||
/// <param name="iv">AES initial value for counter</param>
|
||||
/// <returns>Initialized AES cipher</returns>
|
||||
public static IBufferedCipher CreateAESDecryptionCipher(byte[] key, byte[] iv)
|
||||
{
|
||||
if (key.Length != 16)
|
||||
throw new ArgumentOutOfRangeException(nameof(key));
|
||||
|
||||
var keyParam = new KeyParameter(key);
|
||||
var cipher = CipherUtilities.GetCipher("AES/CTR");
|
||||
cipher.Init(forEncryption: false, new ParametersWithIV(keyParam, iv));
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create AES encryption cipher and intialize
|
||||
/// </summary>
|
||||
/// <param name="key">Byte array representation of 128-bit encryption key</param>
|
||||
/// <param name="iv">AES initial value for counter</param>
|
||||
/// <returns>Initialized AES cipher</returns>
|
||||
public static IBufferedCipher CreateAESEncryptionCipher(byte[] key, byte[] iv)
|
||||
{
|
||||
if (key.Length != 16)
|
||||
throw new ArgumentOutOfRangeException(nameof(key));
|
||||
|
||||
var keyParam = new KeyParameter(key);
|
||||
var cipher = CipherUtilities.GetCipher("AES/CTR");
|
||||
cipher.Init(forEncryption: true, new ParametersWithIV(keyParam, iv));
|
||||
return cipher;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an AES operation using an existing cipher
|
||||
/// </summary>
|
||||
public static void PerformAESOperation(uint size,
|
||||
IBufferedCipher cipher,
|
||||
Stream input,
|
||||
Stream output,
|
||||
Action<string>? progress)
|
||||
{
|
||||
// Get MiB-aligned block count and extra byte count
|
||||
int blockCount = (int)((long)size / (1024 * 1024));
|
||||
int extraBytes = (int)((long)size % (1024 * 1024));
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (blockCount > 0)
|
||||
{
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(1024 * 1024);
|
||||
byte[] processedBytes = cipher.ProcessBytes(readBytes);
|
||||
output.Write(processedBytes);
|
||||
output.Flush();
|
||||
progress?.Invoke($"{i} / {blockCount + 1} MB");
|
||||
}
|
||||
}
|
||||
|
||||
// Process additional data
|
||||
if (extraBytes > 0)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(extraBytes);
|
||||
byte[] finalBytes = cipher.DoFinal(readBytes);
|
||||
output.Write(finalBytes);
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
progress?.Invoke($"{blockCount + 1} / {blockCount + 1} MB... Done!\r\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform an AES operation using two existing ciphers
|
||||
/// </summary>
|
||||
public static void PerformAESOperation(uint size,
|
||||
IBufferedCipher firstCipher,
|
||||
IBufferedCipher secondCipher,
|
||||
Stream input,
|
||||
Stream output,
|
||||
Action<string> progress)
|
||||
{
|
||||
// Get MiB-aligned block count and extra byte count
|
||||
int blockCount = (int)((long)size / (1024 * 1024));
|
||||
int extraBytes = (int)((long)size % (1024 * 1024));
|
||||
|
||||
// Process MiB-aligned data
|
||||
if (blockCount > 0)
|
||||
{
|
||||
for (int i = 0; i < blockCount; i++)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(1024 * 1024);
|
||||
byte[] firstProcessedBytes = firstCipher.ProcessBytes(readBytes);
|
||||
byte[] secondProcessedBytes = secondCipher.ProcessBytes(firstProcessedBytes);
|
||||
output.Write(secondProcessedBytes);
|
||||
output.Flush();
|
||||
progress($"{i} / {blockCount + 1} MB");
|
||||
}
|
||||
}
|
||||
|
||||
// Process additional data
|
||||
if (extraBytes > 0)
|
||||
{
|
||||
byte[] readBytes = input.ReadBytes(extraBytes);
|
||||
byte[] firstFinalBytes = firstCipher.DoFinal(readBytes);
|
||||
byte[] secondFinalBytes = secondCipher.DoFinal(firstFinalBytes);
|
||||
output.Write(secondFinalBytes);
|
||||
output.Flush();
|
||||
}
|
||||
|
||||
progress($"{blockCount + 1} / {blockCount + 1} MB... Done!\r\n");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// TODO: Remove when IO updated
|
||||
#region Byte Arrays
|
||||
|
||||
/// <summary>
|
||||
/// Add an integer value to a number represented by a byte array
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to add to</param>
|
||||
/// <param name="add">Amount to add</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Add(this byte[] self, uint add)
|
||||
{
|
||||
// If nothing is being added, just return
|
||||
if (add == 0)
|
||||
return self;
|
||||
|
||||
// Get the big-endian representation of the value
|
||||
byte[] addBytes = BitConverter.GetBytes(add);
|
||||
Array.Reverse(addBytes);
|
||||
|
||||
// Pad the array out to 16 bytes
|
||||
byte[] paddedBytes = new byte[16];
|
||||
Array.Copy(addBytes, 0, paddedBytes, 12, 4);
|
||||
|
||||
// If the input is empty, just return the added value
|
||||
if (self.Length == 0)
|
||||
return paddedBytes;
|
||||
|
||||
return self.Add(paddedBytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add two numbers represented by byte arrays
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to add to</param>
|
||||
/// <param name="add">Amount to add</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Add(this byte[] self, byte[] add)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0 && add.Length == 0)
|
||||
return [];
|
||||
else if (self.Length > 0 && add.Length == 0)
|
||||
return self;
|
||||
else if (self.Length == 0 && add.Length > 0)
|
||||
return add;
|
||||
|
||||
// Setup the output array
|
||||
int outLength = Math.Max(self.Length, add.Length);
|
||||
byte[] output = new byte[outLength];
|
||||
|
||||
// Loop adding with carry
|
||||
uint carry = 0;
|
||||
for (int i = 0; i < outLength; i++)
|
||||
{
|
||||
int selfIndex = self.Length - i - 1;
|
||||
uint selfValue = selfIndex >= 0 ? self[selfIndex] : 0u;
|
||||
|
||||
int addIndex = add.Length - i - 1;
|
||||
uint addValue = addIndex >= 0 ? add[addIndex] : 0u;
|
||||
|
||||
uint next = selfValue + addValue + carry;
|
||||
carry = next >> 8;
|
||||
|
||||
int outputIndex = output.Length - i - 1;
|
||||
output[outputIndex] = (byte)(next & 0xFF);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform a rotate left on a byte array
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array value to rotate</param>
|
||||
/// <param name="numBits">Number of bits to rotate</param>
|
||||
/// <returns>Rotated byte array value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] RotateLeft(this byte[] self, int numBits)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0)
|
||||
return [];
|
||||
else if (numBits == 0)
|
||||
return self;
|
||||
|
||||
byte[] output = new byte[self.Length];
|
||||
Array.Copy(self, output, output.Length);
|
||||
|
||||
// Shift by bytes
|
||||
while (numBits >= 8)
|
||||
{
|
||||
byte temp = output[0];
|
||||
for (int i = 0; i < output.Length - 1; i++)
|
||||
{
|
||||
output[i] = output[i + 1];
|
||||
}
|
||||
|
||||
output[output.Length - 1] = temp;
|
||||
numBits -= 8;
|
||||
}
|
||||
|
||||
// Shift by bits
|
||||
if (numBits > 0)
|
||||
{
|
||||
byte bitMask = (byte)(8 - numBits), carry, wrap = 0;
|
||||
for (int i = 0; i < output.Length; i++)
|
||||
{
|
||||
carry = (byte)((255 << bitMask & output[i]) >> bitMask);
|
||||
|
||||
// Make sure the first byte carries to the end
|
||||
if (i == 0)
|
||||
wrap = carry;
|
||||
|
||||
// Otherwise, move to the last byte
|
||||
else
|
||||
output[i - 1] |= carry;
|
||||
|
||||
// Shift the current bits
|
||||
output[i] <<= numBits;
|
||||
}
|
||||
|
||||
// Make sure the wrap happens
|
||||
output[output.Length - 1] |= wrap;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// XOR two numbers represented by byte arrays
|
||||
/// </summary>
|
||||
/// <param name="self">Byte array to XOR to</param>
|
||||
/// <param name="xor">Amount to XOR</param>
|
||||
/// <returns>Byte array representing the new value</returns>
|
||||
/// <remarks>Assumes array values are in big-endian format</remarks>
|
||||
public static byte[] Xor(this byte[] self, byte[] xor)
|
||||
{
|
||||
// If either input is empty
|
||||
if (self.Length == 0 && xor.Length == 0)
|
||||
return [];
|
||||
else if (self.Length > 0 && xor.Length == 0)
|
||||
return self;
|
||||
else if (self.Length == 0 && xor.Length > 0)
|
||||
return xor;
|
||||
|
||||
// Setup the output array
|
||||
int outLength = Math.Max(self.Length, xor.Length);
|
||||
byte[] output = new byte[outLength];
|
||||
|
||||
// Loop XOR
|
||||
for (int i = 0; i < outLength; i++)
|
||||
{
|
||||
int selfIndex = self.Length - i - 1;
|
||||
uint selfValue = selfIndex >= 0 ? self[selfIndex] : 0u;
|
||||
|
||||
int xorIndex = xor.Length - i - 1;
|
||||
uint xorValue = xorIndex >= 0 ? xor[xorIndex] : 0u;
|
||||
|
||||
uint next = selfValue ^ xorValue;
|
||||
|
||||
int outputIndex = output.Length - i - 1;
|
||||
output[outputIndex] = (byte)(next & 0xFF);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -86,4 +86,4 @@ namespace NDecrypt.Core
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.IO.Encryption;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace NDecrypt.Core
|
||||
@@ -293,7 +294,7 @@ namespace NDecrypt.Core
|
||||
// KeyX0x18
|
||||
if (KeyX0x18.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(KeyX0x18, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(KeyX0x18, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedKeyX0x18))
|
||||
{
|
||||
@@ -305,7 +306,7 @@ namespace NDecrypt.Core
|
||||
// DevKeyX0x18
|
||||
if (DevKeyX0x18.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(DevKeyX0x18, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(DevKeyX0x18, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedDevKeyX0x18))
|
||||
{
|
||||
@@ -317,7 +318,7 @@ namespace NDecrypt.Core
|
||||
// KeyX0x1B
|
||||
if (KeyX0x1B.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(KeyX0x1B, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(KeyX0x1B, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedKeyX0x1B))
|
||||
{
|
||||
@@ -329,7 +330,7 @@ namespace NDecrypt.Core
|
||||
// DevKeyX0x1B
|
||||
if (DevKeyX0x1B.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(DevKeyX0x1B, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(DevKeyX0x1B, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedDevKeyX0x1B))
|
||||
{
|
||||
@@ -341,7 +342,7 @@ namespace NDecrypt.Core
|
||||
// KeyX0x25
|
||||
if (KeyX0x25.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(KeyX0x25, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(KeyX0x25, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedKeyX0x25))
|
||||
{
|
||||
@@ -353,7 +354,7 @@ namespace NDecrypt.Core
|
||||
// DevKeyX0x25
|
||||
if (DevKeyX0x25.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(DevKeyX0x25, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(DevKeyX0x25, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedDevKeyX0x25))
|
||||
{
|
||||
@@ -365,7 +366,7 @@ namespace NDecrypt.Core
|
||||
// KeyX0x2C
|
||||
if (KeyX0x2C.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(KeyX0x2C, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(KeyX0x2C, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedKeyX0x2C))
|
||||
{
|
||||
@@ -377,7 +378,7 @@ namespace NDecrypt.Core
|
||||
// DevKeyX0x2C
|
||||
if (DevKeyX0x2C.Length > 0)
|
||||
{
|
||||
var cipher = CommonOperations.CreateAESEncryptionCipher(DevKeyX0x2C, TestIV);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(DevKeyX0x2C, TestIV);
|
||||
byte[] actual = cipher.ProcessBytes(TestPattern);
|
||||
if (!actual.EqualsExactly(ExpectedDevKeyX0x2C))
|
||||
{
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#if NET20
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
|
||||
internal sealed class ExtensionAttribute : Attribute {}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -38,11 +38,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BouncyCastle.NetCore" Version="1.9.0" Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="BouncyCastle.NetCore" Version="2.2.1" Condition="!$(TargetFramework.StartsWith(`net2`)) AND !$(TargetFramework.StartsWith(`net3`)) AND !$(TargetFramework.StartsWith(`net40`))" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.0]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.7.5]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.0.1]" />
|
||||
<PackageReference Include="SabreTools.Hashing" Version="[1.5.1]" />
|
||||
<PackageReference Include="SabreTools.IO" Version="[1.7.6]" />
|
||||
<PackageReference Include="SabreTools.Serialization" Version="[2.0.2]" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using SabreTools.Data.Models.N3DS;
|
||||
using SabreTools.IO.Extensions;
|
||||
|
||||
namespace NDecrypt.Core
|
||||
{
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.Data.Models.N3DS;
|
||||
using SabreTools.IO.Encryption;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
using static NDecrypt.Core.CommonOperations;
|
||||
using static SabreTools.Data.Models.N3DS.Constants;
|
||||
|
||||
namespace NDecrypt.Core
|
||||
@@ -211,10 +211,10 @@ namespace NDecrypt.Core
|
||||
Console.WriteLine($"Partition {index}: Decrypting - ExHeader");
|
||||
|
||||
// Create the Plain AES cipher for this partition
|
||||
var cipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey2C, cart.PlainIV(index));
|
||||
var cipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey2C, cart.PlainIV(index));
|
||||
|
||||
// Process the extended header
|
||||
PerformAESOperation(Constants.CXTExtendedDataHeaderLength, cipher, reader, writer, null);
|
||||
AESCTR.PerformOperation(Constants.CXTExtendedDataHeaderLength, cipher, reader, writer, null);
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
|
||||
@@ -265,11 +265,11 @@ namespace NDecrypt.Core
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
uint ctroffsetE = cart.MediaUnitSize / 0x10;
|
||||
byte[] exefsIVWithOffset = cart.ExeFSIV(index).Add(ctroffsetE);
|
||||
var cipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffset);
|
||||
var cipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffset);
|
||||
|
||||
// Setup and perform the decryption
|
||||
exeFsSize -= cart.MediaUnitSize;
|
||||
PerformAESOperation(exeFsSize,
|
||||
AESCTR.PerformOperation(exeFsSize,
|
||||
cipher,
|
||||
reader,
|
||||
writer,
|
||||
@@ -302,7 +302,7 @@ namespace NDecrypt.Core
|
||||
Console.WriteLine($"Partition {index} ExeFS: Decrypting - ExeFS Filename Table");
|
||||
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
var cipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey2C, cart.ExeFSIV(index));
|
||||
var cipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey2C, cart.ExeFSIV(index));
|
||||
|
||||
// Process the filename table
|
||||
byte[] readBytes = reader.ReadBytes((int)cart.MediaUnitSize);
|
||||
@@ -362,15 +362,15 @@ namespace NDecrypt.Core
|
||||
// Create the ExeFS AES ciphers for this partition
|
||||
uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize) / 0x10;
|
||||
byte[] exefsIVWithOffsetForHeader = cart.ExeFSIV(index).Add(ctroffset);
|
||||
var firstCipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey, exefsIVWithOffsetForHeader);
|
||||
var secondCipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
|
||||
var firstCipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey, exefsIVWithOffsetForHeader);
|
||||
var secondCipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
|
||||
|
||||
// Seek to the file entry
|
||||
reader.Seek(exeFsFilesOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsFilesOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
|
||||
// Setup and perform the encryption
|
||||
PerformAESOperation(fileHeader.FileSize,
|
||||
AESCTR.PerformOperation(fileHeader.FileSize,
|
||||
firstCipher,
|
||||
secondCipher,
|
||||
reader,
|
||||
@@ -408,10 +408,10 @@ namespace NDecrypt.Core
|
||||
writer.Seek(romFsOffset, SeekOrigin.Begin);
|
||||
|
||||
// Create the RomFS AES cipher for this partition
|
||||
var cipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey, cart.RomFSIV(index));
|
||||
var cipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey, cart.RomFSIV(index));
|
||||
|
||||
// Setup and perform the decryption
|
||||
PerformAESOperation(romFsSize,
|
||||
AESCTR.PerformOperation(romFsSize,
|
||||
cipher,
|
||||
reader,
|
||||
writer,
|
||||
@@ -636,10 +636,10 @@ namespace NDecrypt.Core
|
||||
Console.WriteLine($"Partition {index}: Encrypting - ExHeader");
|
||||
|
||||
// Create the Plain AES cipher for this partition
|
||||
var cipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey2C, cart.PlainIV(index));
|
||||
var cipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey2C, cart.PlainIV(index));
|
||||
|
||||
// Process the extended header
|
||||
PerformAESOperation(Constants.CXTExtendedDataHeaderLength, cipher, reader, writer, null);
|
||||
AESCTR.PerformOperation(Constants.CXTExtendedDataHeaderLength, cipher, reader, writer, null);
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// In .NET 6.0, this operation is not picked up by the reader, so we have to force it to reload its buffer
|
||||
@@ -691,11 +691,11 @@ namespace NDecrypt.Core
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
uint ctroffsetE = cart.MediaUnitSize / 0x10;
|
||||
byte[] exefsIVWithOffset = cart.ExeFSIV(index).Add(ctroffsetE);
|
||||
var cipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffset);
|
||||
var cipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffset);
|
||||
|
||||
// Setup and perform the encryption
|
||||
uint exeFsSize = cart.GetExeFSSize(index) - cart.MediaUnitSize;
|
||||
PerformAESOperation(exeFsSize,
|
||||
AESCTR.PerformOperation(exeFsSize,
|
||||
cipher,
|
||||
reader,
|
||||
writer,
|
||||
@@ -728,7 +728,7 @@ namespace NDecrypt.Core
|
||||
Console.WriteLine($"Partition {index} ExeFS: Encrypting - ExeFS Filename Table");
|
||||
|
||||
// Create the ExeFS AES cipher for this partition
|
||||
var cipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey2C, cart.ExeFSIV(index));
|
||||
var cipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey2C, cart.ExeFSIV(index));
|
||||
|
||||
// Process the filename table
|
||||
byte[] readBytes = reader.ReadBytes((int)cart.MediaUnitSize);
|
||||
@@ -785,15 +785,15 @@ namespace NDecrypt.Core
|
||||
// Create the ExeFS AES ciphers for this partition
|
||||
uint ctroffset = (fileHeader.FileOffset + cart.MediaUnitSize) / 0x10;
|
||||
byte[] exefsIVWithOffsetForHeader = cart.ExeFSIV(index).Add(ctroffset);
|
||||
var firstCipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey, exefsIVWithOffsetForHeader);
|
||||
var secondCipher = CreateAESDecryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
|
||||
var firstCipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey, exefsIVWithOffsetForHeader);
|
||||
var secondCipher = AESCTR.CreateDecryptionCipher(_keysMap[index].NormalKey2C, exefsIVWithOffsetForHeader);
|
||||
|
||||
// Seek to the file entry
|
||||
reader.Seek(exeFsFilesOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
writer.Seek(exeFsFilesOffset + fileHeader.FileOffset, SeekOrigin.Begin);
|
||||
|
||||
// Setup and perform the encryption
|
||||
PerformAESOperation(fileHeader.FileSize,
|
||||
AESCTR.PerformOperation(fileHeader.FileSize,
|
||||
firstCipher,
|
||||
secondCipher,
|
||||
reader,
|
||||
@@ -838,10 +838,10 @@ namespace NDecrypt.Core
|
||||
}
|
||||
|
||||
// Create the RomFS AES cipher for this partition
|
||||
var cipher = CreateAESEncryptionCipher(_keysMap[index].NormalKey, cart.RomFSIV(index));
|
||||
var cipher = AESCTR.CreateEncryptionCipher(_keysMap[index].NormalKey, cart.RomFSIV(index));
|
||||
|
||||
// Setup and perform the decryption
|
||||
PerformAESOperation(romFsSize,
|
||||
AESCTR.PerformOperation(romFsSize,
|
||||
cipher,
|
||||
reader,
|
||||
writer,
|
||||
|
||||
Reference in New Issue
Block a user