置顶

澳八机器人 Unity AssetBundle 热更新资源保护排查笔记

作者:admin | 分类:澳八机器人 | 浏览:2 | 日期:2026年09月23日


一、排查起点:首包保护了,热更新呢?

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

AssetBundle 本质上是二进制文件,以 UnityFS 开头,缺乏天然的安全保护。未经加密的 Bundle 极易被反编译工具解析,带来资源被盗用、代码逻辑泄露、盗版泛滥等风险。[2]

二、排查链路图

版本清单 → CDN 历史目录 → 本地缓存
    ↓
Bundle 本体加密状态 → 密钥管理策略
    ↓
加载方式(内存/文件)→ 性能与安全的平衡

三、清单与下载地址排查

3.1 版本清单的保护

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

如果路径规则固定:

https://cdn.example.com/hotfix/{channel}/{version}/{bundleName}.ab

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

清单签名是必要的——只验证 Bundle 的 SHA-256 并不完整。如果清单没有签名,文件和 hash 可以一起被替换。[1]

3.2 合理的校验顺序

                        
c#

// 1. 验证清单签名,确认版本信息来自可信发布端

if (!VerifySignature(manifestBytes, manifestSignature, embeddedPublicKey))

RejectUpdate();



BundleEntry entry = signedManifest[bundleName];



// 2. 文件 hash 检查缓存内容是否完整

if (SHA256Hex(cachedEncryptedBundle) != entry.sha256)

RejectAndRedownload(bundleName);



// 3. 最低支持版本,阻止危险回退

if (entry.version < signedManifest.minSupportedVersion)

ForceRedownload(bundleName);

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

四、CDN 历史版本与本地缓存

4.1 历史目录

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

4.2 本地缓存

网络下载的是密文,客户端解密后再把标准 Bundle 写入 Application.persistentDataPath,保护范围就只剩传输阶段。

更稳妥的做法:缓存密文,加载时再解密,而不是缓存解密后的明文。[1]

五、加解密方案

5.1 密钥派生:按 Bundle 和版本隔离

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

                        c#// 伪代码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 不能在同一密钥下重复。工作密钥按资源隔离,可以缩小单个密钥泄露后的影响范围。主密钥仍要避免以明显常量出现在托管代码中。[1]

5.2 Unity 团结引擎原生加密

团结引擎从 1.6.0 版本开始,内置了 AES 加密支持,与构建管线无缝集成:[2]

                        
c#

// 构建时指定密钥

BuildPipeline.SetAssetBundleEncryptKey("0123456789abcdef");



// 构建时启用加密(必须使用 LZ4 压缩)

BuildPipeline.BuildAssetBundles(outputPath,

BuildAssetBundleOptions.ChunkBasedCompression |

BuildAssetBundleOptions.EnableProtection,

EditorUserBuildSettings.activeBuildTarget);



// 加载时指定解密密钥

AssetBundle.SetAssetBundleDecryptKey("0123456789abcdef");

AssetBundle assetBundle = AssetBundle.LoadFromFile("path/to/bundle");

AssetBundle.SetAssetBundleDecryptKey(null);   // 使用后清除

测试数据:加密后的 Bundle 文件大小仅增加 384 字节,加载性能无明显差异。[2]

5.3 YooAsset 四层加密架构(第三方方案)

对于采用 YooAsset 框架的项目,可以借助其四层加密架构做体系化保护:[3]

层级
措施
说明
构建层
Bundle 加密
打包时对 AssetBundle 做 AES 或 XOR 加密
传输层
HTTPS + 签名 URL
防中间人篡改和非法下载
存储层
密文落盘
磁盘缓存保持加密状态
加载层
自定义 Provider
加载时解密,无缝对接资源系统

六、加载方式与性能成本

LZ4 Bundle 原本支持按块读取。如果在外层做整文件加密,可能必须先解密完整文件才能加载,破坏了 LZ4 的分块随机访问优势。[1]

大型 Bundle 通过 AssetBundle.LoadFromMemory 整包载入时,还要注意密文、明文和 Unity 对象同时存在造成的峰值内存问题。

分级策略

实际接入时,建议按资源价值分级:[1]

资源类型
保护级别
方案
新角色、付费皮肤、活动配置
AES-GCM 全量加密
通用 UI 图集、音效
轻量 XOR 或部分加密
场景模型、Shader
仅做 hash 校验
超大 Bundle(>50MB)
特殊
评估分块解密或流式读取

在中低端设备上务必测试加载耗时和峰值内存。

七、发布前检查清单

  • [ ] 首包和热更 Bundle 是否使用同一套保护规则?[1]

  • [ ] CDN 历史版本是否仍保留明文资源

  • [ ] 本地缓存是否重新落成标准 Bundle(应该缓存密文)?

  • [ ] 密钥是否按 Bundle 或版本隔离

  • [ ] 清单是否签名并设置最低支持版本?

  • [ ] 加密是否影响 LZ4 分块读取和加载内存?

  • [ ] Android 和 iOS 两端的行为是否一致?[4]

八、踩坑案例:资源覆盖导致的闪退

某次更新中,30% 的活跃玩家遭遇闪退,排查后发现是典型的 "记忆分裂"问题:[4]

内存中保留对旧 AssetBundle 的引用
               ↓
磁盘文件已经被新版本覆盖
               ↓
"记忆分裂"状态 → 内存访问崩溃

正确做法

  1. 下载新版 Bundle 时,先写临时文件,校验通过后再 rename 覆盖

  2. 确保旧版本的所有加载操作完成后才执行覆盖

  3. 加载新版本时,先 Unload(true) 再 LoadFromFile

九、总结

AssetBundle 热更新资源保护的核心难点在于:首包保护是一次性的,增量更新是持续的。

如果不把加密纳入热更新发布流程,以后每次增量更新都要重新检查有没有明文资源。首包保护做了,更新之后仍然成立——那才算真正覆盖了 AssetBundle 分发链路。[1]

资源加密接入热更新,需要改动构建脚本、加载层、缓存和密钥管理。前期工作量不小,但可以从资源分级入手:高价值资源优先保护,低风险资源轻量校验,在安全性和开发成本之间找到平衡点。[3]

参考资料

  1. 字节暗面. Unity AssetBundle 热更新资源保护排查笔记. 博客园, 2026-09-23.

  2. Unity Technologies. 团结引擎 AssetBundle 新功能深度解析:加密、依赖分析优化与并行构建. Unity 开发者社区, 2026-03-20.

  3. Unity AssetBundle 安全加固:YooAsset 四层加密架构实践. CSDN, 2026-09-18.

  4. Unity 游戏 AssetBundle 热更新踩坑记:资源覆盖下载导致闪退的完整避坑方案. CSDN, 2026-05-07.