Unity AssetBundle 加密

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);
 
————————————————
版权声明:本文为CSDN博主「王王王渣渣」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/wangjiangrong/article/details/89671861

posted @ 2019-11-07 11:59  00000000O  阅读(715)  评论(0编辑  收藏  举报