最近又回归996的节奏了,补了个觉,想到最近做的Unity的AssetBundle加密功能可以拿来分享一下,考虑到做项目都希望资源不能外泄,所以资源加密也算是一个刚需了。
首先我是基于Unity5的方式打包AssetBundle的,关于如何打包AssetBundle就不详细说了,网上随便一搜就一堆博客,而且Unity5相比Unity4打包AssetBundle简单不少。不过打包的时候要注意把后缀改为bytes,就是打包成二进制文件,然后原理就是通过DES加密算法将打包出的bytes文件进行加密,然后使用的时候再解密后通过AssetBundle.LoadFromMemory来加载。原理讲完了,废话不多说,直接上代码。
先写一个加密解密的工具类,里面定义一个加密的Key,这个就是你自己定的密钥。具体DES加密的方法C#有提供,注意using相关的namespace
public class EncryptUtil {
public static string SECRET_KEY = "yoursecret";
public static byte[] Encrypt(byte[] bytes,string secretKey)
{
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
des.Key = ASCIIEncoding.ASCII.GetBytes(secretKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(secretKey);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytes, 0, bytes.Length);
cs.FlushFinalBlock();
cs.Close();
}
byte[] encryptBytes = ms.ToArray();
ms.Close();
return encryptBytes;
}
}
public static byte[] Decrypt(byte[] bytes, string secretKey)
{
using (DESCryptoServiceProvider des = new DESCryptoServiceProvider())
{
des.Key = ASCIIEncoding.ASCII.GetBytes(secretKey);
des.IV = ASCIIEncoding.ASCII.GetBytes(secretKey);
System.IO.MemoryStream ms = new System.IO.MemoryStream();
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytes, 0, bytes.Length);
cs.FlushFinalBlock();
cs.Close();
}
byte[] decryptBytes = ms.ToArray();
ms.Close();
return decryptBytes;
}
}
}
然后是通过创建一个编辑器的工具类来遍历你AssetBundle存放的文件夹下的.bytes资源进行加密操作,具体你的文件目录存在哪不同项目不同,我就不写了,这里只贴出核心的遍历和加密过程
private static void DoEncryptDirectory(DirectoryInfo rootDirectory)
{
FileInfo[] fileInfos = rootDirectory.GetFiles();
for (int i = 0; i < fileInfos.Length; i++)
{
if (fileInfos[i].Extension == ".bytes")
{
byte[] encryptBytes = EncryptUtil.Encrypt(File.ReadAllBytes(fileInfos[i].FullName),EncryptUtil.SECRET_KEY);
File.WriteAllBytes(fileInfos[i].FullName, encryptBytes);
}
}
DirectoryInfo[] subDirectories = rootDirectory.GetDirectories();
for (int i = 0; i < subDirectories.Length; i++)
{
DoEncryptDirectory(subDirectories[i]);
}
}
参数传DirectoryInfo就是你文件夹的信息,如果不懂文件夹操作的话可以先学习下C# 的文件IO相关内容(话说IO可是基础啊。。。看我博客的真的有基础这么差的么。。。残念 = =!)
这样通过执行一个编辑器操作(具体你怎么定义的就怎么操作,关于Unity编辑器如何开发不再叙述,简单的给菜单栏加个按钮什么的其实不难)然后调用这个就可以把你的AssetBundle加密了。
之后怎么加载这个加密后的资源就说下过程吧:用WWW加载完AssetBundle后注意取的是AssetBundle的bytes数据,此时是加密后的bytes,再通过我刚才提供的EncryptUtil解密完这个bytes,就可以通过AssetBundle.LoadFromMemory加载这个AssetBundle了。
PS:最近工作实在太忙,又是做的和AR相关的东西,内容对我来说很多都是全新的需要学习的地方,尤其感觉自己需要学习一下iOS开发了~~~