Unity AssetBundle 热更新资源保护排查笔记

这段时间排查了几个使用 AssetBundle 更新资源的 Unity 项目,发现一个容易被忽略的问题:安装包里的代码和资源已经做过保护,但热更新下载的新 Bundle 仍然保持标准格式。首包和更新资源走了不同链路,安全措施只覆盖了前者。

AssetBundle 负责资源打包和加载,版本检查、下载、缓存、回滚通常由自研框架或 Addressables 处理。下面按实际排查顺序记录几个需要注意的点。

1. 检查版本清单和下载地址

自研框架常见的是 AssetBundleManifest、JSON 或二进制版本表,Addressables 则会检查远程 content catalog。清单中一般包含 Bundle 名称、版本、依赖关系和下载位置。

text 复制代码
https://cdn.example.com/hotfix/{channel}/{version}/{bundleName}.ab

如果路径规则固定,URL 长期有效,拿到清单后就可能批量下载资源。下载文件仍以 UnityFS 开头时,可以直接交给常见 Unity 资源工具解析。

hash 文件名只能隐藏语义,签名 URL 主要限制链接有效期和滥用频率。合法客户端仍要取得文件,所以最终还得处理 Bundle 本体。

2. 当前版本、历史目录和本地缓存要一起看

当前版本加密后,还要检查 CDN 历史目录。灰度、兼容和回滚会保留旧资源,如果早期 Bundle 没补做加密,旧版本仍然可能成为明文入口。

本地缓存也要单独确认。网络下载的是密文,客户端解密后再把标准 Bundle 写入 Application.persistentDataPath,保护范围就只剩传输阶段。比较稳妥的做法是缓存密文,加载时再解密。

密钥不宜全部 Bundle 共用一个固定值,可以按 Bundle 和版本派生工作密钥:

csharp 复制代码
// 伪代码
byte[] context = UTF8($"{bundleName}:{version}");
byte[] salt = SecureRandomBytes(16);
byte[] resourceKey = HKDF(masterKey, salt, info: context);

byte[] nonce = SecureRandomBytes(12);
byte[] encrypted = AESGCMEncrypt(
    resourceKey,
    nonce,
    rawBundleBytes,
    associatedData: context
);

salt 和 nonce 可以随密文保存,但 nonce 不能在同一密钥下重复。工作密钥按资源隔离,可以缩小单个密钥泄露后的影响范围;主密钥仍要避免以明显常量出现在托管代码中。

3. 加密文件和版本清单分别校验

只验证 Bundle 的 SHA-256 并不完整。如果清单没有签名,文件和 hash 可以一起被替换。比较合理的校验顺序如下:

csharp 复制代码
if (!VerifySignature(manifestBytes, manifestSignature, embeddedPublicKey))
    RejectUpdate();

BundleEntry entry = signedManifest[bundleName];

if (SHA256Hex(cachedEncryptedBundle) != entry.sha256)
    RejectAndRedownload(bundleName);

if (entry.version < signedManifest.minSupportedVersion)
    ForceRedownload(bundleName);

清单签名确认版本信息来自可信发布端,文件 hash 检查缓存内容,AES-GCM 认证标签检查密文是否被改动,最低支持版本用于阻止危险回退。

Unity CRC 和 AssetBundle hash 也有各自用途。CRC 可以发现内容损坏或变化,AssetBundle hash 可作为缓存版本值,但二者不能替代发布端签名。

4. 加载方式决定性能成本

LZ4 Bundle 原本支持按块读取。如果在外层做整文件加密,可能必须先解完整文件才能加载。大型 Bundle 通过 AssetBundle.LoadFromMemory 整包载入时,还要注意密文、明文和 Unity 对象同时存在造成的峰值内存。

实际接入时,我一般按资源价值分级:新角色、付费皮肤、活动配置优先保护,普通通用资源采用较轻方案;大 Bundle 评估分块解密、流式读取或自定义 Provider,并在中低端设备上测试加载耗时和峰值内存。

5. 发布前检查项

  • 首包和热更 Bundle 是否使用同一套保护规则;
  • CDN 历史版本是否仍保留明文资源;
  • 本地缓存是否重新落成标准 Bundle;
  • 密钥是否按 Bundle 或版本隔离;
  • 清单是否签名并设置最低支持版本;
  • 加密是否影响 LZ4 分块读取和加载内存。

资源加密接入热更新,需要改动构建脚本、加载层、缓存和密钥管理。前期工作量不小,但如果不把它纳入发布流程,以后每次增量更新都要重新检查有没有明文资源。首包保护是一次性的,更新之后仍然成立,才算真正覆盖了 AssetBundle 分发链路。

相关推荐
魔士于安6 天前
unity 丑陋哥布林 哥布林有humannoid 动画没 带动画
unity·游戏引擎·材质·贴图·模型
小贺儿开发6 天前
Unity 家居视频遥控(细节优化)
科技·unity·程序员·udp·视频·工具·通信
淡海水6 天前
13-04-面试-源码级深度追问链
数据结构·unity·面试·c#·游戏引擎·源码·il2cpp
小小数媒成员7 天前
UGUI 性能优化(详细,全,深入)
开发语言·unity·游戏引擎
林川~017 天前
Unity新输入系统使用笔记
unity·input system
小贺儿开发8 天前
Unity 结合百度AI开放平台 手写文字识别
人工智能·科技·学习·unity·云服务·文字识别·手写文字
字节暗面8 天前
一次游戏安全SO静态分析记录:腾讯ACE与FairGuard加固强度对比
android·逆向工程·游戏加固
林川~018 天前
Unity 万能物理检测工具:射线检测 / 范围检测 / 层级过滤 / 编辑器可视化(可直接拿去用)
游戏·unity·c#·射线检测·通用工具
yi碗汤园8 天前
MQTT消息队列遥测传输协议
网络·网络协议·unity