最近用HybridCLR做热更,热更dll也是AssetBundle,如果不做加密处理,也就意味着资源和热更代码全都赤果果暴露出来了。
GF框架内置的AssetBundle工具自带简单的加密功能:
勾选AB包底部下拉菜单可以选中不同的加载AB方式,不同的加载方式会走DefaultLoadResourceAgentHelper不同的加载方法;
Load From File: 回调ReadFile(string fullPath)方法;
其它:回调ParseBytes(byte[] bytes)方法;
DefaultLoadResourceAgentHelper已经根据AB选择的加载方式,处理了是否解密。所以只需要设置AB的加载方式名称结尾带有Quick Decrypt 和 Decrypt都会自带加密解密功能。使用的加密算法分别为GameFramework.Utility.Encryption.GetQuickXorBytes();GameFramework.Utility.Encryption.GetXorBytes();
自定义加密解密:
加密AB:
首先在AB编辑器中,设置所有AB包的加载方式为Load From Memory,此方式会走LoadResourceAgentHelper的ParseBytes(byte[] bytes)方法,需重写此方法处理解密逻辑;
自定义一个编辑器类AssetBuildHandler : IBuildEventHandler, 继承IBuildEventHandler,实现OnPostprocessPlatform接口,工具打包出AB文件后会回调此方法,在方法中遍历加密AB文件;
public void OnPostprocessPlatform(Platform platform, string workingPath, bool outputPackageSelected, string outputPackagePath, bool outputFullSelected, string outputFullPath, bool outputPackedSelected, string outputPackedPath, bool isSuccess)
{
string targetPath = string.Empty;
bool copyToStreamingAssets = false;
if (outputPackageSelected)
{
targetPath = outputPackagePath;
copyToStreamingAssets = true;
}
else if (outputPackedSelected)
{
targetPath = outputPackedPath;
copyToStreamingAssets = true;
}
else if (outputFullSelected)
{
targetPath = outputFullPath;
}
if (string.IsNullOrEmpty(targetPath))
{
Debug.LogErrorFormat("targetPath is null.");
return;
}
string[] fileNames = Directory.GetFiles(targetPath, "*", SearchOption.AllDirectories);
string streamingAssetsPath = Path.Combine(Application.dataPath, "StreamingAssets");
foreach (string fileName in fileNames)
{
var abAssetName = fileName.Substring(targetPath.Length);
string destFileName = Path.Combine(streamingAssetsPath, abAssetName);
FileInfo destFileInfo = new FileInfo(destFileName);
if (!destFileInfo.Directory.Exists)
{
destFileInfo.Directory.Create();
}
//GameFrameworkVersion.dat和GameFrameworkList.dat不能加密
if (ConstBuiltin.IsEncrypt && !abAssetName.StartsWith("GameFrameworkVersion.") && !abAssetName.StartsWith("GameFrameworkList."))
{
EncryptFile(fileName);
}
if (copyToStreamingAssets) File.Copy(fileName, destFileName);
}
if (isSuccess)
{
if (outputFullSelected || outputFullSelected)
{
EditorUtility.RevealInFinder(targetPath);
}
}
}
private void EncryptFile(string resFile)
{
var data_bytes = File.ReadAllBytes(resFile);
data_bytes = UtilityBuiltin.XOR.QuickXor(data_bytes, ConstBuiltin.RES_KEY);
File.WriteAllBytes(resFile, data_bytes);
}
在AB包Build工具界面选择自己定义的AssetBuildHandler,然后打包即可:
解密:
自定义EncryptLoadResourceAgentHelper继承DefaultLoadResourceAgentHelper,重写ParseBytes(byte[] bytes)方法;
由于前面AB包选择了加载方式为Load From Memory,所以会走ParseBytes方法,然后处理解密即可。
using GameFramework.FileSystem;
using UnityEngine;
using UnityGameFramework.Runtime;
public class EncryptLoadResourceAgentHelper : DefaultLoadResourceAgentHelper
{
public override void ParseBytes(byte[] bytes)
{
if (ConstBuiltin.IsEncrypt)
{
bytes = UtilityBuiltin.XOR.QuickXor(bytes, ConstBuiltin.RES_KEY);
}
base.ParseBytes(bytes);
}
}