找回密码
 立即注册
查看: 305|回复: 0

Unity游戏项目开发中如何做资源加密

[复制链接]
发表于 2022-8-11 12:24 | 显示全部楼层 |阅读模式
Unity的游戏很容易被人反编译出来,然后再重新打包发布,把自己辛辛苦苦开发的游戏,抄写的一丝不挂。很多项目要求要做好资源加密,Unity中如何做好资源加密呢?本文給大家分享加密算法+资源打包整合思路:
(1) 游戏资源加密如何选择加密算法;
(2) Assetsbundle资源包的加密与解密;
对啦!这里有个unity学习交流小组里面聚集了一帮热爱学习unity的零基础小白,也有一些正在从事unity开发的技术大佬,欢迎你来交流学习。
游戏资源包如何选择加密算法
游戏资源包加密的第一件事情就是选一个什么样的加密/解密算法,比较不容易被人破解。我们如何来选择呢?很遗憾的告诉大家,没有任何一个保险的加密解密算法是安全的。杠精第一时间就会来反驳,这怎么可能,我加密了他怎么破解?游戏资源加密注定了加密算法不能用太耗时的加密算法。接下来我们来看下不同加密算法是如何被破解的。


(2) 使用自己实现的加密解密算法,比如,采用二进制亦或来做加密解密,比如,加密定一个二进制掩码mask, 让每个字节都异或这个mask,得到一个新的数据,这样资源就不能被直接识别出来,使用资源得时候,再把加密数据异或一次mask在解密回来到项目中使用。这种破解稍微蛮烦写,需要自己反编译你的解密代码,同时还要找到你的解密密钥key。但是本质也比较容易破解。
加密/解密算法示意如下:


所有从上面分析来看想要不被破解,几乎是很难,就看破解的代价。你这个游戏是否值得。一般我们的目标就是不要让人通过Unity反编译工具就能直接让我们的游戏直接反编译出Unity项目工程,然后重新编译打包发布就可以了。解密算法要快,注定他不会太复杂,密钥单一的放客户端或是网络,注定能获取到。
Assetsbundle资源包的加密与解密


(1) 新建一个类,继承自FileStream, 重写Read/Write函数。代码如下:
using System.IO;

public class MyStream : FileStream {
    const byte KEY = 40; // 密钥mask: 0010 1000

    public MyStream(string path, FileMode mode, FileAccess access, FileShare share, int bufferSize, bool useAsync) :
                               base(path, mode, access, share, bufferSize, useAsync) {

    }

    public MyStream(string path, FileMode mode) : base(path, mode) {

    }

    // 重载读接口,一边读,一遍解密;
    public override int Read(byte[] array, int offset, int count) {
        var index = base.Read(array, offset, count);

        for (int i = 0 ; i < array.Length; i++) {
            array ^= KEY;
        }
        return index;
    }

    public override void Write(byte[] array, int offset, int count) {
        // 重载写接口,先加密再写入;

        for (int i = 0; i < array.Length; i ++) {
            array ^= KEY;
        }
        base.Write(array, offset, count);
    }
}(2) 修改ab包打包工具脚本,再对生成的ab包资源加密一次,打包加密脚本如下:
[MenuItem("Tools/BuildAB")]
static void BuildAB()
{
    …
    // for循环遍历里面的打包后的每个资源Ab包,然后调用进行加密。
    foreach (var name in manifest.GetAllAssetBundles())
    {
        var uniqueSalt = Encoding.UTF8.GetBytes(name);
        var data = File.ReadAllBytes(Path.Combine(Application.streamingAssetsPath, name));
        using (var myStream = new MyStream(Path.Combine(Application.streamingAssetsPath, "encypt_" + name),FileMode.Create))
        {
            myStream.Write(data, 0, data.Length); // 触发MyStream中我们重写的write函数的调用, 完成数据加密
        }
    }
    AssetDatabase.Refresh();
}(3) 解密的时候,读取ab包,使用函数AssetsBundle.LoadFromStream来加载,而这个会触发Stream在Read读数据接口调用,就可以进入我们重载的Read接口,来做解密。代码如下:
var fileStream = new MyStream(Application.streamingAssetsPath + "/encypt_myab.unity3d", FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 4, false))
{
    var myLoadedAssetBundle = AssetBundle.LoadFromStream(fileStream); // 触发MyStream中的Read调用,来解密数据。
}今天的分享就到这里了,关注我们,可以学习更过Unity进阶的一些教程。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-9-22 04:18 , Processed in 0.104369 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表