06-04-YooAsset源码-Unity加密解密服务

源码-加密解密机制

篇章 :06-源码深度-文件系统与下载模块

阅读时间 :约 20 分钟

前置知识:了解 IFileSystem


一、引言

本章将深入解析 YooAsset 加密解密机制的源码实现。加密解密是 YooAsset 资源保护的重要机制,通过加密可以保护游戏资源不被非法获取和修改。深入理解加密解密机制有助于开发者保护游戏资产。

YooAsset 提供了 AES 和 XOR 两种加密方式,支持整体 Bundle 加密和单个资源加密。本章将从源码层面深入解析加密解密机制的实现。


二、IDecryptionServices 接口

2.1 IDecryptionServices 概述

IDecryptionServices 是 YooAsset 加密解密服务的接口:

作用

  • 定义加密解密的统一接口
  • 支持开发者自定义加密方式
  • 与 Collector 集成配置加密选项

2.2 接口定义

复制代码
public interface IDecryptionServices
{
    /// <summary>
    /// 加密方法
    /// </summary>
    /// <param name="fileData">文件数据</param>
    /// <returns>加密后的数据</returns>
    byte[] Encrypt(byte[] fileData);
    
    /// <summary>
    /// 解密方法
    /// </summary>
    /// <param name="fileData">加密的文件数据</param>
    /// <returns>解密后的数据</returns>
    byte[] Decrypt(byte[] fileData);
}

Encrypt 方法详解

Encrypt 方法用于加密文件数据,接收原始数据返回加密数据。

Decrypt 方法详解

Decrypt 方法用于解密文件数据,接收加密数据返回原始数据。

2.3 接口实现

复制代码
public class DecryptionServices : IDecryptionServices
{
    private byte[] _encryptionKey;
    
    public DecryptionServices(byte[] encryptionKey)
    {
        _encryptionKey = encryptionKey;
    }
    
    public byte[] Encrypt(byte[] fileData)
    {
        // 使用 AES 加密
        return AESHelper.Encrypt(fileData, _encryptionKey);
    }
    
    public byte[] Decrypt(byte[] fileData)
    {
        // 使用 AES 解密
        return AESHelper.Decrypt(fileData, _encryptionKey);
    }
}

构造函数详解

通过构造函数注入加密密钥。

方法实现详解

实现加密和解密方法,调用 AES 加密库。

2.4 接入方式

复制代码
var package = YooAssets.CreatePackage("DefaultPackage");
var initParameters = new HostPlayModeParameters();
initParameters.AssetBundleDecryptionServices = new DecryptionServices(encryptionKey);
YooAssets.InitPackage(package);

接入方式详解

通过初始化参数注入解密服务。


三、AES 加密

3.1 AES 概述

AES(Advanced Encryption Standard)是高级加密标准:

特点

  • 对称加密算法
  • 安全性高
  • 性能较好
  • 标准化程度高

YooAsset 中的应用

  • Bundle 整体加密
  • 单个资源加密

3.2 AES 实现

复制代码
public class AESHelper
{
    public static byte[] Encrypt(byte[] data, byte[] key)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            
            // 生成 IV
            aes.GenerateIV();
            byte[] iv = aes.IV;
            
            // 创建加密器
            using (ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, iv))
            using (MemoryStream ms = new MemoryStream())
            {
                // 写入 IV
                ms.Write(iv, 0, iv.Length);
                
                using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                {
                    cs.Write(data, 0, data.Length);
                    cs.FlushFinalBlock();
                }
                return ms.ToArray();
            }
        }
    }
    
    public static byte[] Decrypt(byte[] data, byte[] key)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.PKCS7;
            
            // 读取 IV
            byte[] iv = new byte[16];
            Array.Copy(data, 0, iv, 0, 16);
            aes.IV = iv;
            
            // 创建解密器
            using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
            using (MemoryStream ms = new MemoryStream(data, 16, data.Length - 16))
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            using (MemoryStream output = new MemoryStream())
            {
                cs.CopyTo(output);
                return output.ToArray();
            }
        }
    }
}

AES.Create 详解

使用 .NET 提供的 Aes 类创建 AES 实例。

CBC 模式详解

CBC(Cipher Block Chaining)模式是常用的分组加密模式。

PKCS7 填充详解

PKCS7 是常用的填充方式。

IV(初始化向量)详解

IV 用于增加加密的随机性,每次加密生成新的 IV。

3.3 AES 性能优化

复制代码
public class AESHelper
{
    public static byte[] EncryptOptimized(byte[] data, byte[] key)
    {
        using (Aes aes = Aes.Create())
        {
            aes.Key = key;
            aes.GenerateIV();
            
            // 使用 AES.CreateEncryptor 预创建加密器
            using (ICryptoTransform encryptor = aes.CreateEncryptor())
            {
                return encryptor.TransformFinalBlock(data, 0, data.Length);
            }
        }
    }
}

预创建加密器详解

预创建加密器可以减少加密过程中的开销。

TransformFinalBlock 详解

TransformFinalBlock 一次性完成加密,避免多次写入。


四、XOR 加密

4.1 XOR 概述

XOR(异或)是一种简单的加密方式:

特点

  • 简单、快速
  • 安全性较低
  • 适合临时加密
  • 适合小文件加密

YooAsset 中的应用

  • Bundle 整体加密
  • 单个文件加密

4.2 XOR 实现

复制代码
public class XORHelper
{
    public static byte[] Encrypt(byte[] data, byte[] key)
    {
        byte[] result = new byte[data.Length];
        for (int i = 0; i < data.Length; i++)
        {
            result[i] = (byte)(data[i] ^ key[i % key.Length]);
        }
        return result;
    }
    
    public static byte[] Decrypt(byte[] data, byte[] key)
    {
        return Encrypt(data, key); // XOR 解密与加密相同
    }
}

XOR 原理详解

XOR 加密通过将数据与密钥进行异或运算。

XOR 解密详解

XOR 加密是可逆的,解密与加密相同。

4.3 XOR 性能优化

复制代码
public class XORHelper
{
    public static unsafe byte[] EncryptOptimized(byte[] data, byte[] key)
    {
        byte[] result = new byte[data.Length];
        int keyLength = key.Length;
        
        fixed (byte* pData = data, pKey = key, pResult = result)
        {
            for (int i = 0; i < data.Length; i++)
            {
                pResult[i] = (byte)(pData[i] ^ pKey[i % keyLength]);
            }
        }
        return result;
    }
}

unsafe 代码优化详解

使用 unsafe 代码和指针可以提高性能。

适用场景详解

unsafe 代码适合性能要求高的场景,但需要注意平台兼容性。

4.4 XOR 安全性

XOR 安全性较低

  • 容易被破解
  • 不适合保护重要资源
  • 适合临时加密

增强安全性的方法

  • 使用更长的密钥
  • 多重 XOR
  • 结合其他加密方式

五、加密策略

5.1 整体加密 vs 单个资源加密

整体加密详解

对整个 Bundle 文件加密,加密粒度大,性能好但灵活性低。

单个资源加密详解

对 Bundle 中的每个资源单独加密,加密粒度小,灵活性高但性能差。

YooAsset 推荐

默认使用整体 Bundle 加密,在安全和性能之间取得平衡。

5.2 加密范围

复制代码
// 1. 所有 Bundle 都加密
parameters.EnableEncryption = true;

// 2. 指定 Bundle 加密
[AssetBundleEncryptRule("critical_bundle")]
public bool ShouldEncrypt(string bundleName) { return true; }

全量加密详解

所有 Bundle 都加密,安全性最高,但性能开销最大。

选择性加密详解

只加密关键 Bundle,平衡安全性和性能。

5.3 加密密钥管理

复制代码
public class KeyManager
{
    private byte[] _key;
    
    public KeyManager()
    {
        // 从安全存储加载密钥
        _key = LoadKeyFromSecureStorage();
    }
    
    public byte[] GetKey()
    {
        return _key;
    }
    
    private byte[] LoadKeyFromSecureStorage()
    {
        // 从安全存储加载密钥
        // 例如:Keystore、Keychain 等
    }
}

密钥管理的重要性

密钥管理是加密安全的关键,密钥不能明文存储在代码中。

密钥管理方式

  • iOS:Keychain
  • Android:Keystore
  • 通用:加密配置文件

5.4 加密与性能

加密对性能的影响

  • 增加打包时间
  • 增加运行时解密开销
  • 增加包体大小

性能优化

  • 只加密关键资源
  • 使用硬件加速(AES-NI)
  • 缓存解密结果

六、加密实战

6.1 完整加密实现示例

复制代码
public class BundleEncryptionExample
{
    public static void SetupEncryption()
    {
        // 1. 创建 Package
        var package = YooAssets.CreatePackage("GamePackage");
        
        // 2. 配置加密服务
        var initParameters = new HostPlayModeParameters();
        byte[] encryptionKey = new byte[32]; // 256 位密钥
        new System.Random().NextBytes(encryptionKey);
        initParameters.AssetBundleDecryptionServices = new DecryptionServices(encryptionKey);
        
        // 3. 初始化 Package
        YooAssets.InitPackage(package);
    }
}

public class DecryptionServices : IDecryptionServices
{
    private byte[] _key;
    
    public DecryptionServices(byte[] key)
    {
        _key = key;
    }
    
    public byte[] Encrypt(byte[] fileData)
    {
        return AESHelper.Encrypt(fileData, _key);
    }
    
    public byte[] Decrypt(byte[] fileData)
    {
        return AESHelper.Decrypt(fileData, _key);
    }
}

完整流程详解

  1. 创建 Package
  2. 配置加密服务
  3. 初始化 Package

密钥生成详解

使用随机数生成 32 字节(256 位)的密钥。

6.2 加密配置

复制代码
[CreateAssetMenu(fileName = "PackageConfig", menuName = "YooAsset/Package Config")]
public class PackageConfig : ScriptableObject
{
    public bool EnableEncryption;
    public string EncryptionKey;
    public EEncryptionType EncryptionType = EEncryptionType.AES;
}

配置参数详解

  • EnableEncryption:是否启用加密
  • EncryptionKey:加密密钥
  • EncryptionType:加密类型

6.3 加密测试

复制代码
public class EncryptionTest
{
    public static void TestEncryption()
    {
        byte[] original = System.Text.Encoding.UTF8.GetBytes("Hello, YooAsset!");
        byte[] key = new byte[32];
        new System.Random().NextBytes(key);
        
        // 加密
        byte[] encrypted = AESHelper.Encrypt(original, key);
        
        // 解密
        byte[] decrypted = AESHelper.Decrypt(encrypted, key);
        
        // 验证
        Debug.Assert(System.Text.Encoding.UTF8.GetString(decrypted) == "Hello, YooAsset!");
    }
}

测试目的详解

验证加密和解密的正确性。

测试步骤详解

  1. 准备原始数据
  2. 生成密钥
  3. 加密
  4. 解密
  5. 验证

七、总结

本章深入解析了 YooAsset 加密解密机制的源码实现,包括:

  • IDecryptionServices 接口:接口定义、实现、接入方式
  • AES 加密:AES 概述、实现、性能优化
  • XOR 加密:XOR 概述、实现、性能优化、安全性
  • 加密策略:整体加密 vs 单个资源加密、加密范围、密钥管理
  • 加密实战:完整实现示例、配置、测试

通过深入理解加密解密机制,开发者可以保护游戏资源不被非法获取和修改。


下一篇YooAsset 快速入门

相关推荐
trigger3338 小时前
desk-health-web-community-post
前端
倒流时光三十年8 小时前
Logback 系列(7):常用 Appender(控制台 / 文件 / 滚动文件)
java·前端·logback
至乐活着8 小时前
深入Python内存管理与垃圾回收:从引用计数到分代回收的实战解析
python·性能优化·内存管理·垃圾回收·引用计数
Csvn8 小时前
页面「穿越」之谜:React 中因 key 值不正确导致的渲染 Bug 排查实战
前端
浅水壁虎8 小时前
前端技术_TypeScript(第一章)
前端
laboratory agent开发9 小时前
企业AI Agent落地前,先回答四个工程问题
java·前端·人工智能
微三云 - 廖会灵 (私域系统开发)9 小时前
电商系统国际化架构设计:多语言、多币种、多时区、多税制的全链路实现
java·前端·数据库
不简说10 小时前
JS 代码技巧 vol.5 — 10 个错误处理套路,从 try/catch 到 Error Boundary
前端·javascript·程序员