简体   繁体   中英

Unity AES Encryptor

I've integrated this module in Unity. I want to be able to decrypt file that were encrypted with AES.

Here is a part of my code:

using UnityEngine;
using System.Collections;
using System.Security.Cryptography;

public class LoadEncryptBundle : MonoBehaviour {

// Use this for initialization
void Start () {
    StartCoroutine(Load());
}

// Update is called once per frame
void Update () {

}

// string url = "http://www.mywebsite.com/mygame/assetbundles/assetbundle1.unity3d";
string url = "file:///G:/UnityDecryptBundle/Bundles/3341_windows.unity3d.aes";
IEnumerator Load()
{
    // Start a download of the encrypted assetbundle
    WWW www = new WWW(url);

    // Wait for download to complete
    yield return www;
    System.Diagnostics.Debug.WriteLine("File downloaded");
    // Get the byte data
    byte[] encryptedData = www.bytes;

    // Decrypt the AssetBundle data
    byte[] decryptedData = AvoEx.AesEncryptor.Decrypt(encryptedData);

    // Create an AssetBundle from the bytes array

    AssetBundleCreateRequest acr = AssetBundle.LoadFromMemoryAsync(decryptedData);
    yield return acr;

    AssetBundle bundle = acr.assetBundle;

    // Load the object asynchronously
    AssetBundleRequest request = bundle.LoadAllAssetsAsync<GameObject>();

    // Wait for completion
    yield return request;


    // Get the reference to the loaded object
    GameObject[] objs = request.allAssets as GameObject[];
    foreach (GameObject obj in request.allAssets)
    {
        Instantiate(obj);
    }
    // Unload the AssetBundles compressed contents to conserve memory
    bundle.Unload(false);

    // Frees the memory from the web stream
    www.Dispose();
}

}

Here i download the encrypted file and try to decrypt it using the key and params set in another file:

using UnityEngine;
using System;
using System.Text;
using System.Security.Cryptography;
using System.Linq;

/* See the "http://avoex.com/avoex/default-license/" for the full license governing this code. */

namespace AvoEx
{
    // based on http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp
    public static class AesEncryptor
    {
        // only the 128, 192, and 256-bit key sizes are specified in the AES standard. https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
        const int keySize = 16; // keySize must be 16, 24 or 32 bytes.
        const string keyString = "coincoincoincoin"; // EDIT 'keyString' BEFORE RELEASE. keyString must be longer than keySize.
        // DO NOT EDIT 'keySize, keyString' AFTER RELEASE YOUR PROJECT.
        // if you change keyString, you can not decrypt saved data encrypted by old keyString.

        // The size of the IV property must be the same as the BlockSize property divided by 8.
        // https://msdn.microsoft.com/ko-kr/library/system.security.cryptography.symmetricalgorithm.iv(v=vs.110).aspx
        const int IvLength = 16;
        static readonly UTF8Encoding encoder;
        static readonly AesManaged aes;

        static AesEncryptor()
        {

            encoder = new UTF8Encoding();
            aes = new AesManaged { Key = encoder.GetBytes(keyString).Take(keySize).ToArray() };
            aes.BlockSize = IvLength * 8; // only the 128-bit block size is specified in the AES standard.
        }

        public static byte[] GenerateIV()
        {
            aes.GenerateIV();
            return aes.IV;
        }

        #region PREPEND_VECTOR
        /// <summary>
        /// encrypt bytes with random vector. prepend vector to result.
        /// </summary>
        public static byte[] Encrypt(byte[] buffer)
        {
            aes.GenerateIV();
            using (ICryptoTransform encryptor = aes.CreateEncryptor())
            {
                byte[] inputBuffer = encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
                return aes.IV.Concat(inputBuffer).ToArray();
            }
        }

        /// <summary>
        /// decrypt bytes, encrypted by Encrypt(byte[]).
        /// </summary>
        public static byte[] Decrypt(byte[] buffer)
        {
            byte[] iv = buffer.Take(IvLength).ToArray();
            using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, iv))
            {

                return decryptor.TransformFinalBlock(buffer, IvLength, buffer.Length - IvLength);
            }
        }
        #endregion PREPEND_VECTOR

        #region CUSTOM_KEY
        /// <summary>
        /// not prepend vector to result. you must use DecryptIV(byte[], byte[]) to decrypt.
        /// </summary>
        public static byte[] EncryptIV(byte[] buffer, byte[] IV)
        {
            return EncryptKeyIV(buffer, aes.Key, IV);
        }

        /// <summary>
        /// decrypt bytes, encrypted by EncryptIV(byte[], byte[]).
        /// </summary>
        public static byte[] DecryptIV(byte[] buffer, byte[] IV)
        {
            return DecryptKeyIV(buffer, aes.Key, IV);
        }

        public static byte[] EncryptKeyIV(byte[] buffer, byte[] key, byte[] IV)
        {
            using (ICryptoTransform encryptor = aes.CreateEncryptor(key, IV))
            {
                return encryptor.TransformFinalBlock(buffer, 0, buffer.Length);
            }
        }

        public static byte[] DecryptKeyIV(byte[] buffer, byte[] key, byte[] IV)
        {
            using (ICryptoTransform decryptor = aes.CreateDecryptor(key, IV))
            {
                return decryptor.TransformFinalBlock(buffer, 0, buffer.Length);
            }
        }
        #endregion CUSTOM_KEY

        #region ENCRYPT_TO_STRING
        // string
        /// <summary>
        /// encrypt string with random vector. prepend vector to result.
        /// </summary>
        public static string Encrypt(string unencrypted)
        {
            return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
        }

        /// <summary>
        /// decrypt string, encrypted by Encrypt(string).
        /// </summary>
        [Obsolete("Decrypt(string) has been made obsolete. Please use the DecryptString(string).")]
        public static string Decrypt(string encrypted)
        {
            return DecryptString(encrypted);
        }
        public static string DecryptString(string encrypted)
        {
            return DecryptString(Convert.FromBase64String(encrypted));
        }
        public static string DecryptString(byte[] encrypted)
        {
            byte[] bytesDecrypted = Decrypt(encrypted);
            return encoder.GetString(bytesDecrypted, 0, bytesDecrypted.Length);
        }

        /// <summary>
        /// not prepend vector to result. you must use DecryptIV(string, byte[]) to decrypt.
        /// </summary>
        public static string EncryptIV(string unencrypted, byte[] vector)
        {
            return Convert.ToBase64String(EncryptIV(encoder.GetBytes(unencrypted), vector));
        }

        /// <summary>
        /// decrypt string, encrypted by EncryptIV(string, byte[]).
        /// </summary>
        public static string DecryptIV(string encrypted, byte[] vector)
        {
            byte[] bytesDecrypted = DecryptIV(Convert.FromBase64String(encrypted), vector);
            return encoder.GetString(bytesDecrypted, 0, bytesDecrypted.Length);
        }

        // bool
        public static string Encrypt(bool unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static bool DecryptBool(string encrypted)
        {
            return DecryptBool(Convert.FromBase64String(encrypted));
        }
        public static bool DecryptBool(byte[] encrypted)
        {
            return BitConverter.ToBoolean(Decrypt(encrypted), 0);
        }

        // char
        public static string Encrypt(char unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static char DecryptChar(string encrypted)
        {
            return DecryptChar(Convert.FromBase64String(encrypted));
        }
        public static char DecryptChar(byte[] encrypted)
        {
            return BitConverter.ToChar(Decrypt(encrypted), 0);
        }

        // double
        public static string Encrypt(double unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static double DecryptDouble(string encrypted)
        {
            return DecryptDouble(Convert.FromBase64String(encrypted));
        }
        public static double DecryptDouble(byte[] encrypted)
        {
            return BitConverter.ToDouble(Decrypt(encrypted), 0);
        }

        // float
        public static string Encrypt(float unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static float DecryptFloat(string encrypted)
        {
            return DecryptFloat(Convert.FromBase64String(encrypted));
        }
        public static float DecryptFloat(byte[] encrypted)
        {
            return BitConverter.ToSingle(Decrypt(encrypted), 0);
        }

        // int
        public static string Encrypt(int unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }
        public static int DecryptInt(string encrypted)
        {
            return DecryptInt(Convert.FromBase64String(encrypted));
        }
        public static int DecryptInt(byte[] encrypted)
        {
            return BitConverter.ToInt32(Decrypt(encrypted), 0);
        }

        // long
        public static string Encrypt(long unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static long DecryptLong(string encrypted)
        {
            return DecryptLong(Convert.FromBase64String(encrypted));
        }
        public static long DecryptLong(byte[] encrypted)
        {
            return BitConverter.ToInt64(Decrypt(encrypted), 0);
        }

        // short
        public static string Encrypt(short unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static short DecryptShort(string encrypted)
        {
            return DecryptShort(Convert.FromBase64String(encrypted));
        }
        public static short DecryptShort(byte[] encrypted)
        {
            return BitConverter.ToInt16(Decrypt(encrypted), 0);
        }

        // uint
        public static string Encrypt(uint unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static uint DecryptUInt(string encrypted)
        {
            return DecryptUInt(Convert.FromBase64String(encrypted));
        }
        public static uint DecryptUInt(byte[] encrypted)
        {
            return BitConverter.ToUInt32(Decrypt(encrypted), 0);
        }

        // ulong
        public static string Encrypt(ulong unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static ulong DecryptULong(string encrypted)
        {
            return DecryptULong(Convert.FromBase64String(encrypted));
        }
        public static ulong DecryptULong(byte[] encrypted)
        {
            return BitConverter.ToUInt64(Decrypt(encrypted), 0);
        }

        // ushort
        public static string Encrypt(ushort unencrypted)
        {
            return Convert.ToBase64String(Encrypt(BitConverter.GetBytes(unencrypted)));
        }

        public static ushort DecryptUShort(string encrypted)
        {
            return DecryptUShort(Convert.FromBase64String(encrypted));
        }
        public static ushort DecryptUShort(byte[] encrypted)
        {
            return BitConverter.ToUInt16(Decrypt(encrypted), 0);
        }
        #endregion ENCRYPT_TO_STRING
    }
}

Key is the good one but i get this error when i run it:

CryptographicException: Invalid input block size.

Mono.Security.Cryptography.SymmetricTransform.FinalDecrypt (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)

Mono.Security.Cryptography.SymmetricTransform.TransformFinalBlock (System.Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)

AvoEx.AesEncryptor.Decrypt (System.Byte[] buffer) (at Assets/AvoEx/AesEncryptor/AesEncryptor.cs:63)

LoadEncryptBundle+<Load>c__Iterator1.MoveNext () (at Assets/LoadEncryptBundle.cs:31)

UnityEngine.SetupCoroutine.InvokeMoveNext (IEnumerator enumerator, IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)

I have no clue how to debug this,

Thanks in advance for your answers,

Happy Black Friday / Thanksgiving

I'm not familiar with the specific library, but it appears from the documentation linked that it is indeed expecting the block size in bits rather than bytes . You can use LegalBlockSizes to verify the expected block size.

Do you know the cipher block mode of operation in use here? It's likely that it defaults to CBC but that's not indicated anywhere. CBC requires that the cipher text is padded to a block boundary. Have you verified that the cipher text is padded correctly and is n + 1 blocks (ie (n + 1) * 8 bits) long? The first 16 bytes are the IV used to encrypt this message, and the remaining bytes (must be divisible by 16 ) are the actual cipher text.

Can you successfully decrypt this content using another implementation of AES? There are five line implementations in a number of languages ( Ruby , Java , etc.) which will let you verify the sample data is correct.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM