Skip to content

15 · 加密与发布 ​

本章讲解如何用 SDK 加密资源并发布游戏到各平台。

即解即用加密 ​

灵泛引擎的加密方案是即解即用——资源保持散文件部署,读取时检测加密头并按需解密。

LFEN 格式 ​

加密后的文件使用 LFEN 格式:

LFEN(4字节魔数) | 版本(1) | nonce(12) | tag(16) | 密文
  • 加密算法:AES-256-GCM
  • 每个文件独立 nonce,防重放攻击
  • 读取时自动检测 LFEN 魔数头,加密则解密,不加密则直接使用

加密范围 ​

按文件类型勾选加密,不是全量加密:

类型是否加密说明
.story✅ 推荐剧本源码,最需要保护
.png / .jpg可选图片资源
.wav / .mp3可选音频资源
.mp4可选视频
.dll / .exe❌二进制不需要(.NET 自有保护)

全类型可加密

引擎支持全类型文件加密。你可以根据需求勾选——只加密 .story,或加密所有资源。

SDK 发布流程 ​

1. 打开构建页 ​

在 SDK 中打开项目,点击左侧「构建」。

2. 配置加密 ​

配置项说明
资源加密总开关开启后按文件类型勾选
文件类型勾选勾选要加密的扩展名
密钥分片数1~8,默认 1(分片存储增加逆向难度)

3. 选择平台 ​

选择目标平台对应的 .csproj:

平台项目后缀
Windows.Desktop.Windows.csproj
Linux.Desktop.Linux.csproj
macOS.Desktop.Mac.csproj
Android.Android.csproj
iOS.iOS.csproj
Browser.Browser.csproj

4. 构建 ​

SDK 自动执行:

  1. 杀掉项目目录下运行的进程(防 PDB 锁定)
  2. 生成 GeneratedKeys.cs(密钥,放核心项目 Security/ 目录)
  3. dotnet publish 平台项目
  4. 原地加密 Stories/ 和 Media/ 中的指定文件
  5. 生成 manifest.lfmanifest(清单)

密钥注入 ​

GeneratedKeys.cs ​

SDK 的 KeyInjector 自动生成密钥文件:

csharp
// Security/GeneratedKeys.cs(自动生成,不要手动编辑)
namespace MyGame.Security;

public class GeneratedKeyProvider : IEncryptionKeyProvider
{
    private static readonly byte[] _combined = new byte[] { ... };

    public byte[]? GetKey() => GetKeyArray();

    public static ReadOnlySpan<byte> GetKey() => _combined;
    public static byte[] GetKeyArray() => _combined;
}

密钥分片 ​

分片数 > 1 时,密钥被拆分存储在多个位置,静态构造函数合并:

csharp
// 分片 1
private static readonly byte[] _s1 = new byte[] { 0xAB, 0xCD, ... };
// 分片 2
private static readonly byte[] _s2 = new byte[] { 0xEF, 0x12, ... };

static GeneratedKeyProvider()
{
    _combined = new byte[_s1.Length + _s2.Length];
    _s1.CopyTo(_combined, 0);
    _s2.CopyTo(_combined, _s1.Length);
}

分片的作用

分片不增加加密强度,但增加逆向工程难度——密钥碎片散布在代码中,不容易一次性提取。

DI 注册 ​

在 ServiceExtensions.cs 中注册密钥提供者:

csharp
public static IServiceCollection AddGameSecurity(this IServiceCollection services)
{
    services.AddSingleton<IEncryptionKeyProvider, GeneratedKeyProvider>();
    return services;
}

发布产物 ​

publish/
├── MyGame.exe              # 可执行文件
├── LingFanEngine.dll       # 引擎 DLL
├── Stories/                # 剧本(部分已加密)
│   ├── title/
│   │   └── title_main.story   ← LFEN 格式
│   └── chapter1/
├── Media/                  # 媒体资源(部分已加密)
│   ├── Images/
│   └── Audio/
├── manifest.lfmanifest     # 加密清单
└── *.dll                   # 其他依赖

散文件部署

引擎不打包资源。Stories/ 和 Media/ 保持散文件结构。这让补丁更新很简单——只需替换改动的文件。

跨平台发布 ​

Windows ​

bash
dotnet publish -c Release -r win-x64
dotnet publish -c Release -r win-arm64

macOS ​

bash
dotnet publish -c Release -r osx-arm64    # Apple Silicon
dotnet publish -c Release -r osx-x64      # Intel

Linux ​

bash
dotnet publish -c Release -r linux-x64

Android / iOS / Browser ​

需要对应的平台项目,SDK 会自动处理依赖和配置。

AOT 编译 ​

灵泛引擎完全 AOT 友好。启用 AOT 获得更快启动和更低内存:

xml
<!-- 在平台 .csproj 中 -->
<PropertyGroup>
  <PublishAot>true</PublishAot>
</PropertyGroup>

AOT 注意事项

  • 禁止反射和动态代码生成
  • JSON 序列化用 source generator(引擎已内置)
  • 第三方库需确认 AOT 兼容

补丁更新 ​

由于散文件部署,补丁更新很简单:

  1. 替换改动的 .story / .png / .wav 文件
  2. 如果启用了加密,新文件也需要用相同密钥加密
  3. 更新 manifest.lfmanifest

玩家只需下载增量文件,不需要重新下载整个游戏。

动手练习 ​

发布你的第一个游戏:

  1. 在 SDK 中打开项目
  2. 点击「构建」
  3. 开启资源加密,勾选 .story
  4. 选择 Windows 平台
  5. 点击构建
  6. 在 bin/Release/ 下找到发布产物
  7. 运行 MyGame.exe 验证

下一步 ​

所有功能都学完了!最后一章完整作品将组装一个完整的示例游戏。

基于 .NET 10 + Avalonia 12 · Apache-2.0 License