AssetBundle加密解密

资源打包参考另一篇博客,Unity 简单打包脚本

AES(Advanced Encryption Standard)是一种对称加密算法,是目前广泛使用的加密标准之一。AES使用相同的密钥来进行加密和解密,密钥长度可以是128位、192位或256位。它将数据分成固定长度的数据块,然后对每个数据块进行加密。AES算法采用替代、置换和混合的技术,通过多轮的操作来实现高强度的加密。

C#提供了内置的加密库,其中包括对AES加密算法的支持,需要添加命名空间System.Security.Cryptography
使用AES算法,除了密钥,还需要一个IV(Initialization Vector,初始化向量)作用是在加密中引入随机性,以确保相同的明文在每次加密时都产生不同的密文,从而增强加密的安全性。

加密算法通常可以用于加密任何类型的文件,这里以加密bundle为例子

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

public static class AesEncryption
{
    private static string keyString = "YourSecretKey123";
    private static string ivString = "123456";

    private static byte[] key = Encoding.UTF8.GetBytes(keyString);
    //IV 必须是 16 字节
    private static byte[] iv = Encoding.UTF8.GetBytes(ivString.PadRight(16, '\0'));

    public static bool EncryptFile(string inputPath, string outputPath)
    {
        try
        {
            using (Aes aes = Aes.Create())
            {
                aes.Key = key;
                aes.IV = iv;

                // 读取待加密的文件
                using (FileStream inputFileStream = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
                {
                    // 创建一个内存流,用于存放加密后的数据
                    using (MemoryStream memoryStream = new MemoryStream())
                    {
                        // 创建加密转换器和加密流
                        using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
                        {
                            inputFileStream.CopyTo(cryptoStream);
                            cryptoStream.FlushFinalBlock();

                            // 获取加密后的数据
                            byte[] encryptedData = memoryStream.ToArray();

                            // 将加密后的内容写入输出文件
                            File.WriteAllBytes(outputPath, encryptedData);
                        }
                    }
                }
            }
            return true;
        }
        catch(Exception e)
        {
            Debug.LogError(e.ToString());
            return false;
        }
    }

    public static byte[] DecryptFile(string inputPath)
    {
        try
        {
            using (Aes aes = Aes.Create())
            {
                aes.Key = key;
                aes.IV = iv;

                // 打开加密后的文件
                using (FileStream inputFile = new FileStream(inputPath, FileMode.Open, FileAccess.Read))
                {
                    // 创建一个内存流,用于存放解密后的数据
                    using (MemoryStream outputStream = new MemoryStream())
                    {
                        // 创建解密转换器和解密流
                        using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
                        using (CryptoStream cryptoStream = new CryptoStream(inputFile, decryptor, CryptoStreamMode.Read))
                        {
                            // 将加密后的文件内容解密并写入内存流
                            cryptoStream.CopyTo(outputStream);
                        }

                        // 获取解密后的数据
                        return outputStream.ToArray();
                    }
                }
            }
         
        }
        catch (Exception e)
        {
            Debug.LogError("解密失败:" + e.ToString());
            return null;
        }
    }
}

代码中的密钥和 IV 可以设置成通过网络传输获取,或者把代码打成 dll,然后加壳

Editor下测试加密文件

using System.IO;
using UnityEditor;
using UnityEngine;

public static class EncryptionBundle
{
    public static bool EncryptionFile(string inputPath, string outputPath)
    {
        return AesEncryption.EncryptFile(inputPath, outputPath);
    }

    [MenuItem("Tools/加密资源")]
    public static void BuildDirectory()
    {
        string inputPath = Application.streamingAssetsPath;
        string outputPath = Application.dataPath + "/EncryptionAsset/";
        string[] files = Directory.GetFiles(inputPath);
        for (int i = 0; i < files.Length; i++)
        {
            string filePath = files[i];
            if (filePath.EndsWith(".meta"))
            {
                continue;
            }
            string fileName = Path.GetFileName(filePath);
            bool result = EncryptionFile(filePath, outputPath + fileName);
            Debug.Log("加密" + (result ? "成功" : "失败") + " " + filePath);
        }

        AssetDatabase.Refresh();
    }
}

运行时先解密,然后从内存中加载bundle

using System.Collections.Generic;
using UnityEngine;

public class LoadEncryptedBundle : MonoBehaviour
{
    private AssetBundleManifest _manifest;
    private List<string> _abList = new List<string>();
    private Dictionary<string, GameObject> _assetDict = new Dictionary<string, GameObject>();
    //加密后资源所在路径
    private string encryptionPath = Application.dataPath + "/EncryptionAsset/";

    void Start()
    {
        LoadManifest();
        LoadGameObject("plane");
    }

    private void LoadManifest()
    {
        AssetBundle assetBundle = DecryptionFile(encryptionPath + "StreamingAssets");
        _manifest = assetBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
    }

    private AssetBundle DecryptionFile(string path)
    {
        byte[] bytes = AesEncryption.DecryptFile(path);
        if (bytes != null)
        {
            return AssetBundle.LoadFromMemory(bytes);
        }
        return null;
    }

    private void LoadGameObject(string abName)
    {
        if (string.IsNullOrEmpty(abName))
            return;

        abName = abName.ToLower();

        //先加载依赖资源
        string[] dependens = _manifest.GetAllDependencies(abName);
        for (int i = 0; i < dependens.Length; ++i)
        {
            if (!_abList.Contains(dependens[i]))
            {
                DecryptionFile(encryptionPath + dependens[i]);
                _abList.Add(dependens[i]);
            }
        }

        if (!_abList.Contains(abName))
        {
            AssetBundle ab = DecryptionFile(encryptionPath + abName);
            _abList.Add(abName);
            _assetDict.Add(abName, ab.LoadAsset<GameObject>(abName));
        }

        if (_assetDict.ContainsKey(abName))
        {
            GameObject.Instantiate(_assetDict[abName]);
        }
    }
}

你可能感兴趣的:(资源管理,unity)