public static byte[] SignMemeData(byte[] input, MemeKeyIndex keyIndex = MemeKeyIndex.PokedexAndSaveFile)
        {
            // Validate Input
            if (input.Length < 0x60)
            {
                throw new ArgumentException("Cannot memesign a buffer less than 0x60 bytes in size!");
            }
            var memekey = new MemeKey(keyIndex);

            if (!memekey.CanResign)
            {
                throw new ArgumentException("Cannot sign with the specified memekey!");
            }

            var output = (byte[])input.Clone();

            // Copy in the SHA1 signature
            using (var sha1 = SHA1.Create())
            {
                Array.Copy(sha1.ComputeHash(input, 0, input.Length - 8), 0, output, output.Length - 8, 8);
            }

            // Perform AES operations
            output = memekey.AesEncrypt(output);
            var sigBuffer = new byte[0x60];

            Array.Copy(output, output.Length - 0x60, sigBuffer, 0, 0x60);
            sigBuffer[0] &= 0x7F;
            sigBuffer     = memekey.RsaPrivate(sigBuffer);
            sigBuffer.CopyTo(output, output.Length - 0x60);
            return(output);
        }
        public static bool VerifyMemeData(byte[] input, out byte[] output, MemeKeyIndex keyIndex)
        {
            output = null;
            if (input.Length < 0x60)
            {
                return(false);
            }
            var memekey = new MemeKey(keyIndex);

            output = (byte[])input.Clone();

            var sigBuffer = new byte[0x60];

            Array.Copy(input, input.Length - 0x60, sigBuffer, 0, 0x60);
            sigBuffer = memekey.RsaPublic(sigBuffer);
            using (var sha1 = SHA1.Create())
                foreach (var orVal in new byte[] { 0, 0x80 })
                {
                    sigBuffer[0x0] |= orVal;
                    sigBuffer.CopyTo(output, output.Length - 0x60);
                    memekey.AesDecrypt(output).CopyTo(output, 0);
                    // Check for 8-byte equality.
                    if (BitConverter.ToUInt64(sha1.ComputeHash(output, 0, output.Length - 0x8), 0) ==
                        BitConverter.ToUInt64(output, output.Length - 0x8))
                    {
                        return(true);
                    }
                }
            output = null;
            return(false);
        }
Exemple #3
0
        public static bool VerifyMemeData(byte[] input, out byte[] output, MemeKeyIndex keyIndex)
        {
            if (input.Length < 0x60)
            {
                output = input;
                return(false);
            }
            var key = new MemeKey(keyIndex);

            output = (byte[])input.Clone();

            var sigBuffer = key.RsaPublic(input.SliceEnd(input.Length - 0x60));

            using var sha1 = SHA1.Create();
            if (DecryptCompare(output, sigBuffer, key, sha1))
            {
                return(true);
            }
            sigBuffer[0x0] |= 0x80;
            if (DecryptCompare(output, sigBuffer, key, sha1))
            {
                return(true);
            }

            output = input;
            return(false);
        }
Exemple #4
0
 private static byte[] GetMemeData(MemeKeyIndex key)
 {
     return(key switch
     {
         MemeKeyIndex.LocalWireless => DER_LW,
         MemeKeyIndex.FriendlyCompetition => DER_0,
         MemeKeyIndex.LiveCompetition => DER_1,
         MemeKeyIndex.RentalTeam => DER_2,
         MemeKeyIndex.PokedexAndSaveFile => DER_3,
         MemeKeyIndex.GaOle => DER_4,
         MemeKeyIndex.MagearnaEvent => DER_5,
         MemeKeyIndex.MoncolleGet => DER_6,
         MemeKeyIndex.IslandScanEventSpecial => DER_7,
         MemeKeyIndex.TvTokyoDataBroadcasting => DER_8,
         MemeKeyIndex.CapPikachuEvent => DER_9,
         MemeKeyIndex.Unknown10 => DER_A,
         MemeKeyIndex.Unknown11 => DER_B,
         MemeKeyIndex.Unknown12 => DER_C,
         MemeKeyIndex.Unknown13 => DER_D,
         _ => throw new ArgumentOutOfRangeException(nameof(key), key, null)
     });
Exemple #5
0
        // Constructor
        public MemeKey(MemeKeyIndex key)
        {
            DER = GetMemeData(key);
            var _N = DER.AsSpan(0x18, 0x61).ToArray();
            var _E = DER.AsSpan(0x7B, 3).ToArray();

            _N.AsSpan().Reverse();
            _E.AsSpan().Reverse();
            N = new BigInteger(_N);
            E = new BigInteger(_E);

            if (key == MemeKeyIndex.PokedexAndSaveFile)
            {
                var _D = D_3.AsSpan().ToArray();
                _D.AsSpan().Reverse();
                D = new BigInteger(_D);
            }
            else
            {
                D = INVALID;
            }
        }
Exemple #6
0
        // Constructor
        public MemeKey(MemeKeyIndex key)
        {
            DER = GetMemeData(key);
            var _N = new byte[0x61];
            var _E = new byte[0x3];

            Array.Copy(DER, 0x18, _N, 0, 0x61);
            Array.Copy(DER, 0x7B, _E, 0, 3);
            Array.Reverse(_N);
            N = new BigInteger(_N);
            Array.Reverse(_E);
            E = new BigInteger(_E);

            if (key == MemeKeyIndex.PokedexAndSaveFile)
            {
                var _D = (byte[])D_3.Clone();
                Array.Reverse(_D);
                D = new BigInteger(_D);
            }
            else
            {
                D = INVALID;
            }
        }
        // Constructor
        public MemeKey(MemeKeyIndex key)
        {
            GetMemeData(key, out byte[] d, out byte[] der);
            DER = der;
            var _N = new byte[0x61];
            var _E = new byte[0x3];

            Array.Copy(der, 0x18, _N, 0, 0x61);
            Array.Copy(der, 0x7B, _E, 0, 3);
            Array.Reverse(_N);
            N = new BigInteger(_N);
            Array.Reverse(_E);
            E = new BigInteger(_E);
            if (d != null)
            {
                var _D = (byte[])d.Clone();
                Array.Reverse(_D);
                D = new BigInteger(_D);
            }
            else
            {
                D = INVALID;
            }
        }
Exemple #8
0
 private static byte[] GetMemeData(MemeKeyIndex key) => key switch
 {
        public static bool VerifyMemeData(byte[] input, out byte[] output, int offset, int length, MemeKeyIndex keyIndex)
        {
            var data = new byte[length];

            Array.Copy(input, offset, data, 0, length);
            if (VerifyMemeData(data, out output, keyIndex))
            {
                var newOutput = (byte[])input.Clone();
                output.CopyTo(newOutput, offset);
                output = newOutput;
                return(true);
            }
            output = null;
            return(false);
        }
Exemple #10
0
        // Helper Method to retrieve data for loading
        private static void GetMemeData(MemeKeyIndex key, out byte[] d, out byte[] der)
        {
            d = null;

            switch (key)
            {
            case MemeKeyIndex.LocalWireless:
                der = DER_LW;
                break;

            case MemeKeyIndex.FriendlyCompetition:
                der = DER_0;
                break;

            case MemeKeyIndex.LiveCompetition:
                der = DER_1;
                break;

            case MemeKeyIndex.RentalTeam:
                der = DER_2;
                break;

            case MemeKeyIndex.PokedexAndSaveFile:
                der = DER_3;
                d   = D_3;
                break;

            case MemeKeyIndex.GaOle:
                der = DER_4;
                break;

            case MemeKeyIndex.MagearnaEvent:
                der = DER_5;
                break;

            case MemeKeyIndex.MoncolleGet:
                der = DER_6;
                break;

            case MemeKeyIndex.IslandScanEventSpecial:
                der = DER_7;
                break;

            case MemeKeyIndex.TvTokyoDataBroadcasting:
                der = DER_8;
                break;

            case MemeKeyIndex.CapPikachuEvent:
                der = DER_9;
                break;

            case MemeKeyIndex.Unknown10:
                der = DER_A;
                break;

            case MemeKeyIndex.Unknown11:
                der = DER_B;
                break;

            case MemeKeyIndex.Unknown12:
                der = DER_C;
                break;

            case MemeKeyIndex.Unknown13:
                der = DER_D;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(key), key, null);
            }
        }
Exemple #11
0
 public void TestVerifyKnownKeys(MemeKeyIndex keyIndex, byte[] key)
 {
     MemeCrypto.VerifyMemeData(key, out _, keyIndex).Should().BeTrue("because they key should be valid");
 }