Minor rearranging

This commit is contained in:
Kurt 2021-01-07 18:05:21 -08:00
parent 19d40f61f5
commit 1138cd44bc
5 changed files with 76 additions and 65 deletions

View file

@ -5,6 +5,9 @@ using System.Security.Cryptography;
namespace PKHeX.Core
{
/// <summary>
/// Key for crypto with <see cref="MemeCrypto"/> binaries.
/// </summary>
public sealed class MemeKey
{
/// <summary> Distinguished Encoding Rules </summary>
@ -82,7 +85,8 @@ namespace PKHeX.Core
{
var curblock = new byte[0x10];
Array.Copy(data, ((data.Length / 0x10) - 1 - i) * 0x10, curblock, 0, 0x10);
temp = AesEcbDecrypt(key, temp.Xor(curblock));
var temp1 = Xor(temp, curblock);
temp = AesEcbDecrypt(key, temp1);
temp.CopyTo(outdata, ((data.Length / 0x10) - 1 - i) * 0x10);
}
@ -93,7 +97,7 @@ namespace PKHeX.Core
// Well, (a ^ a) = 0. so (block first ^ subkey) ^ (block last ^ subkey)
// = block first ^ block last ;)
Array.Copy(outdata, ((data.Length / 0x10) - 1) * 0x10, temp, 0, 0x10);
temp = temp.Xor(outdata.Slice(0, 0x10));
temp = Xor(temp, outdata.Slice(0, 0x10));
for (var ofs = 0; ofs < 0x10; ofs += 2) // Imperfect ROL implementation
{
byte b1 = temp[ofs + 0], b2 = temp[ofs + 1];
@ -109,7 +113,8 @@ namespace PKHeX.Core
{
var curblock = new byte[0x10];
Array.Copy(outdata, 0x10 * i, curblock, 0, 0x10);
Array.Copy(curblock.Xor(subkey), 0, outdata, 0x10 * i, 0x10);
var temp1 = Xor(curblock, subkey);
Array.Copy(temp1, 0, outdata, 0x10 * i, 0x10);
}
// Now we have Phase1Encrypt(buf).
@ -118,7 +123,9 @@ namespace PKHeX.Core
{
var curblock = new byte[0x10];
Array.Copy(outdata, i * 0x10, curblock, 0, 0x10);
AesEcbDecrypt(key, curblock).Xor(temp).CopyTo(outdata, i * 0x10);
var temp1 = AesEcbDecrypt(key, curblock);
var temp2 = Xor(temp1, temp);
temp2.CopyTo(outdata, i * 0x10);
curblock.CopyTo(temp, 0);
}
@ -143,12 +150,14 @@ namespace PKHeX.Core
{
var curblock = new byte[0x10];
Array.Copy(data, i * 0x10, curblock, 0, 0x10);
temp = AesEcbEncrypt(key, temp.Xor(curblock));
var temp1 = Xor(temp, curblock);
temp = AesEcbEncrypt(key, temp1);
temp.CopyTo(outdata, i * 0x10);
}
// In between - CMAC stuff
temp = temp.Xor(outdata.Slice(0, 0x10));
var inbet = outdata.Slice(0, 0x10);
temp = Xor(temp, inbet);
for (var ofs = 0; ofs < 0x10; ofs += 2) // Imperfect ROL implementation
{
byte b1 = temp[ofs + 0], b2 = temp[ofs + 1];
@ -165,8 +174,10 @@ namespace PKHeX.Core
{
var curblock = new byte[0x10];
Array.Copy(outdata, ((data.Length / 0x10) - 1 - i) * 0x10, curblock, 0, 0x10);
byte[] temp2 = curblock.Xor(subkey);
Array.Copy(AesEcbEncrypt(key, temp2).Xor(temp), 0, outdata, ((data.Length / 0x10) - 1 - i) * 0x10, 0x10);
byte[] temp2 = Xor(curblock, subkey);
byte[] temp3 = AesEcbEncrypt(key, temp2);
byte[] temp4 = Xor(temp3, temp);
Array.Copy(temp4, 0, outdata, ((data.Length / 0x10) - 1 - i) * 0x10, 0x10);
temp2.CopyTo(temp, 0);
}
@ -176,6 +187,16 @@ namespace PKHeX.Core
return outbuf;
}
private static byte[] Xor(byte[] b1, byte[] b2)
{
if (b1.Length != b2.Length)
throw new ArgumentException("Cannot xor two arrays of uneven length!");
var x = new byte[b1.Length];
for (var i = 0; i < b1.Length; i++)
x[i] = (byte)(b1[i] ^ b2[i]);
return x;
}
/// <summary>
/// Perform Rsa Decryption
/// </summary>
@ -300,55 +321,4 @@ namespace PKHeX.Core
private static readonly byte[] D_3 = "00775455668FFF3CBA3026C2D0B26B8085895958341157AEB03B6B0495EE57803E2186EB6CB2EB62A71DF18A3C9C6579077670961B3A6102DABE5A194AB58C3250AED597FC78978A326DB1D7B28DCCCB2A3E014EDBD397AD33B8F28CD525054251".ToByteArray();
#endregion
}
public static class StringExtentions
{
public static byte[] ToByteArray(this string toTransform)
{
var result = new byte[toTransform.Length / 2];
for (int i = 0; i < result.Length; i++)
{
var ofs = i << 1;
var _0 = toTransform[ofs + 0];
var _1 = toTransform[ofs + 1];
result[i] = DecodeTuple(_0, _1);
}
return result;
}
private static bool IsNum(char c) => (uint)(c - '0') <= 9;
private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5;
private static byte DecodeTuple(char _0, char _1)
{
byte result;
if (IsNum(_0))
result = (byte)((_0 - '0') << 4);
else if (IsHexUpper(_0))
result = (byte)((_0 - 'A' + 10) << 4);
else
throw new ArgumentOutOfRangeException(nameof(_0));
if (IsNum(_1))
result |= (byte)(_1 - '0');
else if (IsHexUpper(_1))
result |= (byte)(_1 - 'A' + 10);
else
throw new ArgumentOutOfRangeException(nameof(_1));
return result;
}
}
public static class ByteArrayExtensions
{
public static byte[] Xor(this byte[] b1, byte[] b2)
{
if (b1.Length != b2.Length)
throw new ArgumentException("Cannot xor two arrays of uneven length!");
var x = new byte[b1.Length];
for (var i = 0; i < b1.Length; i++)
x[i] = (byte)(b1[i] ^ b2[i]);
return x;
}
}
}
}

View file

@ -1,5 +1,8 @@
namespace PKHeX.Core
{
/// <summary>
/// Different Key Types used for <see cref="MemeCrypto"/>
/// </summary>
public enum MemeKeyIndex
{
LocalWireless = -1,
@ -18,4 +21,4 @@ namespace PKHeX.Core
Unknown12 = 12,
Unknown13 = 13
}
}
}

View file

@ -74,7 +74,7 @@ namespace PKHeX.Core
keys[i] = BigEndian.ToUInt16(slot, 8 + (i * 2));
// Decrypt Slot
Data = GCSaveUtil.Decrypt(slot, 0x00010, 0x27FD8, keys);
Data = GeniusCrypto.Decrypt(slot, 0x00010, 0x27FD8, keys);
}
// Get Offset Info
@ -140,7 +140,7 @@ namespace PKHeX.Core
ushort[] keys = new ushort[4];
for (int i = 0; i < keys.Length; i++)
keys[i] = BigEndian.ToUInt16(Data, 8 + (i * 2));
byte[] newSAV = GCSaveUtil.Encrypt(Data, 0x10, 0x27FD8, keys);
byte[] newSAV = GeniusCrypto.Encrypt(Data, 0x10, 0x27FD8, keys);
// Put save slot back in original save data
byte[] newFile = MC != null ? MC.SelectedSaveData : (byte[]) State.BAK.Clone();

View file

@ -235,7 +235,7 @@ namespace PKHeX.Core
{
var keys = GetKeys(input, i);
Array.Copy(input, i, output, i, 8);
GCSaveUtil.Decrypt(input, i + 8, i + 0x1C0000, keys, output);
GeniusCrypto.Decrypt(input, i + 8, i + 0x1C0000, keys, output);
}
return output;
}
@ -247,7 +247,7 @@ namespace PKHeX.Core
{
var keys = GetKeys(input, i);
Array.Copy(input, i, output, i, 8);
GCSaveUtil.Encrypt(input, i + 8, i + 0x1C0000, keys, output);
GeniusCrypto.Encrypt(input, i + 8, i + 0x1C0000, keys, output);
}
return output;
}

View file

@ -77,5 +77,43 @@ namespace PKHeX.Core
}
return -1;
}
/// <summary>
/// Converts an all-caps hex string to a byte array.
/// </summary>
public static byte[] ToByteArray(this string toTransform)
{
var result = new byte[toTransform.Length / 2];
for (int i = 0; i < result.Length; i++)
{
var ofs = i << 1;
var _0 = toTransform[ofs + 0];
var _1 = toTransform[ofs + 1];
result[i] = DecodeTuple(_0, _1);
}
return result;
}
private static bool IsNum(char c) => (uint)(c - '0') <= 9;
private static bool IsHexUpper(char c) => (uint)(c - 'A') <= 5;
private static byte DecodeTuple(char _0, char _1)
{
byte result;
if (IsNum(_0))
result = (byte)((_0 - '0') << 4);
else if (IsHexUpper(_0))
result = (byte)((_0 - 'A' + 10) << 4);
else
throw new ArgumentOutOfRangeException(nameof(_0));
if (IsNum(_1))
result |= (byte)(_1 - '0');
else if (IsHexUpper(_1))
result |= (byte)(_1 - 'A' + 10);
else
throw new ArgumentOutOfRangeException(nameof(_1));
return result;
}
}
}