Unity AssetBundle 加密

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wangjiangrong/article/details/89671861

前言

昨天面试,面试官问了些有关AB包相关的知识点,问到了有关AB加密的问题,由于之前没有了解过,而且感觉是一个蛮重要的一个环节。所以今天查了查相关知识,记录一下(要是不对的地方,欢迎大佬们帮忙纠正)

我们都知道我们的ab包都是放在包体的可读文件夹下,玩家是可以很轻易的取出我们的ab包,若没有做加密处理的话,按照正常的读取ab包的操作,任何人都可以加载出我们ab包的内容,然后并使用,这显然是很不安全的。

这里我们用一个简单的加密算法,对我们的ab包进行加密。

思路

在得到ab包后,我们遍历StreamingAssets目录,获取所有的ab包,然后逐个将ab包转为byte[],然后byte[]中的每一位都和设定好的秘钥key执行异或操作(加密)。最后将新的byte[]重新写入文件中,即加密完成。

在ab读取的时候,也要从原本的AssetBundle.LoadFromFile()方法转为用AssetBundle.LoadFromMemory()方法,传入的byte[]参数同样是将要读取的ab包转为byte[],然后每一位和秘钥key执行异或操作(解密)。

注:A 异或 Key = B,B 异或 Key = A。

代码实现

本代码是跟着之前打包ab包的工程内加的,首先我们先定义好秘钥和加密解密的方法。

using System.IO;

namespace Utility {

    public class FileUtility {

        ......

        const byte m_key = 157;
        /// <summary>
        /// 加密/解密
        /// </summary>
        /// <param name="targetData">文件流</param>
        public static void Encypt(ref byte[] targetData) {
            //加密,与key异或,解密的时候同样如此
            int dataLength = targetData.Length;
            for(int i = 0; i < dataLength; ++i) {
                targetData[i] = (byte)(targetData[i] ^ m_key);
            }
        }
    }
}

然后我们在打包完成的时候,读取ab包,并进行加密。(注demo里把ab包全部重新生成了下,然后把StreamAssets下的所有文件进行了加密,实际情况我们只针对差异包加密。同时要避免重复加密的情况)

namespace AssetBundle {
    public static class BuildAssetBundle {

        ......

        public static IEnumerator EncyptAssetBundle() {
            yield return "开始加密...";
            //遍历streamingAssets目录下所有的ab包,逐个进行加密
            foreach(var f in new DirectoryInfo(AssetBundleUtility.streamingAssetsPath).GetFiles("*.u", SearchOption.AllDirectories)) {
                Byte[] temp = File.ReadAllBytes(f.FullName);
                yield return "加密文件:"+ f.FullName;
                FileUtility.Encypt(ref temp);
                File.WriteAllBytes(f.FullName, temp);
            }
            yield return "加密完成...";
        }

        ......

    }
}

然后在打包流程结束后,调用加密方法

namespace AssetBundle {
    public class BuildAssetBundleWindow : EditorWindow {

        ......

        void Build() {

            ......

            #region 流程

            // 打包
            if (BuildAssetBundleSetting.instance.isBuild) {
                count++;

                IEnumerator buildEtor = BuildAssetBundle.Build();
                while (buildEtor.MoveNext()) {
                    yield return buildEtor.Current;
                }
            }

            //加密
            IEnumerator encyptEtor = BuildAssetBundle.EncyptAssetBundle();
            while(encyptEtor.MoveNext()) {
                yield return encyptEtor.Current;
            }

            #endregion

            BuildAssetBundleSetting.instance.Save();

            ......
        }

        ......
    }
}

这个时候,打包加密已经完成了,我们打一次ab包,得到结果如下

在读取ab的时候,若还是使用AssetBundle.LoadFromFile()方法,则会报错如下。这样别的用户就不能随意的读取我们ab包的资源了。

正确的读法如下,使用LoadFromMemory()方法:

ab = new AssetBundleItem(path, fileName, isHasDependence);
byte[] stream = File.ReadAllBytes(ab.pathName);
//解密
FileUtility.Encypt(ref stream);
ab.assetBundle = AssetBundle.LoadFromMemory(stream);
cacheAssetBundleItemDic.Add(path, ab);

猜你喜欢

转载自blog.csdn.net/wangjiangrong/article/details/89671861
今日推荐