Unity AES加密器

时间:2016-11-25 14:40:12

标签: c# encryption unity3d aes

我在Unity中集成了this module。 我希望能够解密用AES加密的文件。

以下是我的代码的一部分:

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();
}

}

在这里,我下载加密文件并尝试使用另一个文件中设置的密钥和参数对其进行解密:

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是好的,但是当我运行它时会出现这个错误:

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)

我不知道如何调试它,

提前感谢您的回答,

黑色星期五/感恩节快乐

1 个答案:

答案 0 :(得分:0)

我不熟悉特定的库,但是documentation linked显示它确实期望bits中的块大小而不是bytes。您可以使用LegalBlockSizes来验证预期的块大小。

您知道这里使用的cipher block mode of operation吗?它可能默认为CBC,但在任何地方都没有显示。 CBC要求将密文填充到块边界。您是否验证了密文正确填充并且 n + 1 块(即(n + 1) * 8位)长?第一个16字节是用于加密此消息的IV,其余字节(必须可被16整除)是实际的密文。

您是否可以使用其他AES实现成功解密此内容?有多种语言(RubyJava等)有五种实现方式,可以验证样本数据是否正确。