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);
        }
        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);
        }
Beispiel #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);
        }
Beispiel #4
0
        private static bool DecryptCompare(byte[] output, byte[] sigBuffer, MemeKey key, SHA1 sha1)
        {
            sigBuffer.CopyTo(output, output.Length - 0x60);
            key.AesDecrypt(output).CopyTo(output, 0);
            // Check for 8-byte equality.
            var hash     = sha1.ComputeHash(output, 0, output.Length - 0x8);
            var computed = BitConverter.ToUInt64(hash, 0);
            var existing = BitConverter.ToUInt64(output, output.Length - 0x8);

            return(computed == existing);
        }
Beispiel #5
0
        public static bool VerifyMemePOKE(byte[] input, out byte[] output)
        {
            if (input.Length < 0x60)
            {
                throw new ArgumentException("Invalid POKE buffer!");
            }
            var memeLen   = input.Length - 8;
            var memeIndex = MemeKeyIndex.PokedexAndSaveFile;

            for (var i = input.Length - 8; i >= 0; i--)
            {
                if (BitConverter.ToUInt32(input, i) != POKE)
                {
                    continue;
                }

                var keyIndex = BitConverter.ToInt32(input, i + 4);
                if (!MemeKey.IsValidPokeKeyIndex(keyIndex))
                {
                    continue;
                }

                memeLen   = i;
                memeIndex = (MemeKeyIndex)keyIndex;
                break;
            }

            foreach (var len in new[] { memeLen, memeLen - 2 }) // Account for Pokédex QR Edge case
            {
                if (VerifyMemeData(input, out output, 0, len, memeIndex))
                {
                    return(true);
                }

                if (VerifyMemeData(input, out output, 0, len, MemeKeyIndex.PokedexAndSaveFile))
                {
                    return(true);
                }
            }

            output = input;
            return(false);
        }