在 Unity 项目中,为了保护资源(如纹理、音频、模型和脚本等)免受未经授权的访问和盗用,可以采用多种加密和保护方案。以下是几种常见的 Unity 资源加密方案:
一. 加密和解密资源文件
常见的加密算法有 AES、RSA 等。
1.AES 加密
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
public static class EncryptionUtils
{
private static readonly string encryptionKey = "YourEncryptionKey"; // 替换为你的密钥
public static byte[] Encrypt(byte[] data)
{
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(encryptionKey);
aes.GenerateIV();
using (MemoryStream ms = new MemoryStream())
{
ms.Write(aes.IV, 0, aes.IV.Length);
using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(data, 0, data.Length);
cs.FlushFinalBlock();
}
return ms.ToArray();
}
}
}
public static byte[] Decrypt(byte[] data)
{
using (Aes aes = Aes.Create())
{
aes.Key = Encoding.UTF8.GetBytes(encryptionKey);
using (MemoryStream ms = new MemoryStream(data))
{
byte[] iv = new byte[aes.IV.Length];
ms.Read(iv, 0, iv.Length);
aes.IV = iv;
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
using (MemoryStream output = new MemoryStream())
{
cs.CopyTo(output);
return output.ToArray();
}
}
}
}
}
}
2.RSA 加密
using System;
using System.Security.Cryptography;
using System.Text;
public static class RsaExample
{
private static RSAParameters publicKey;
private static RSAParameters privateKey;
// 生成公钥和私钥
public static void GenerateKeys()
{
using (RSA rsa = RSA.Create())
{
publicKey = rsa.ExportParameters(false); // 只导出公钥部分
privateKey = rsa.ExportParameters(true); // 导出公钥和私钥
}
}
// 使用公钥加密数据
public static byte[] Encrypt(string plainText)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(publicKey);
byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);
return rsa.Encrypt(plainBytes, RSAEncryptionPadding.Pkcs1);
}
}
// 使用私钥解密数据
public static string Decrypt(byte[] cipherText)
{
using (RSA rsa = RSA.Create())
{
rsa.ImportParameters(privateKey);
byte[] plainBytes = rsa.Decrypt(cipherText, RSAEncryptionPadding.Pkcs1);
return Encoding.UTF8.GetString(plainBytes);
}
}
public static void Main()
{
GenerateKeys(); // 生成密钥对
string original = "Hello, World!";
byte[] encrypted = Encrypt(original);
string decrypted = Decrypt(encrypted);
Console.WriteLine($"Original: {
original}");
Console.WriteLine($"Encrypted: {
Convert.ToBase64String(encrypted)}");
Console.WriteLine($"Decrypted: {
decrypted}");
}
}
有时你可能需要将密钥存储在文件或其他介质中,可以使用 XML 格式导出和导入密钥。以下是如何导出和导入密钥的示例:
导出密钥
public static void ExportKeys()
{
using (RSA rsa = RSA.Create())
{
// 导出公钥为 XML
string publicKeyXml = rsa.ToXmlString(false);
File.WriteAllText("publicKey.xml", publicKeyXml);
// 导出私钥为 XML
string privateKeyXml = rsa.ToXmlString(true);
File.WriteAllText("privateKey.xml", privateKeyXml);
}
}
导入密钥
public static void ImportKeys()
{
using (RSA rsa = RSA.Create())
{
// 从 XML 文件中读取公钥
string publicKeyXml = File.ReadAllText("publicKey.xml");
rsa.FromXmlString(publicKeyXml);
publicKey = rsa.ExportParameters(false);
// 从 XML 文件中读取私钥
string privateKeyXml = File.ReadAllText("privateKey.xml");
rsa.FromXmlString(privateKeyXml);
privateKey = rsa.ExportParameters(true);
}
}
这样,你就可以将密钥导出为 XML 文件保存,并在需要时导入这些密钥进行加密和解密操作。
3. AES vs RSA
-
AES:
- 对称加密算法:同一密钥用于加密和解密。
- 速度快,适合大数据量的加密。
- 常用于数据传输加密和存储加密。
-
RSA:
- 非对称加密算法:使用一对密钥(公钥和私钥),公钥用于加密,私钥用于解密。
- 速度较慢,适合小数据量的加密(如加密密钥、数字签名)。
- 常用于安全传输对称密钥、身份验证和数字签名。
在实际应用中,常常结合使用两者:通过 RSA 加密对称密钥,再使用 AES 进行数据加密,以兼顾安全性和性能。
4 在构建前加密资源
你可以在 Unity 的构建过程中加密资源文件。使用 AssetPostprocessor
或自定义构建脚本来加密资源:
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using System.IO;
public class EncryptAssets : IPreprocessBuildWithReport
{
public int callbackOrder => 0;
public void OnPreprocessBuild(BuildReport report)
{
string[] assetPaths = AssetDatabase.GetAllAssetPaths();
foreach (string assetPath in assetPaths)
{
if (assetPath.EndsWith(".txt")) // 根据需要修改文件类型
{
byte[] data = File.ReadAllBytes(assetPath);
byte[] encryptedData = EncryptionUtils.Encrypt(data);
File.WriteAllBytes(assetPath, encryptedData);
}
}
}
}
二、 使用 Asset Bundles 加密
Asset Bundles 是 Unity 提供的一种资源打包方式,可以在构建时对资源进行打包,并在运行时加载。你可以在创建 Asset Bundle 时对资源进行加密,并在加载时解密。
1. 创建加密的 Asset Bundle
使用 BuildPipeline.BuildAssetBundles
构建 Asset Bundle,并在保存之前对数据进行加密:
using UnityEditor;
using System.IO;
public class BuildEncryptedAssetBundles
{
[MenuItem("Assets/Build Encrypted AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/AssetBundles";
if (!Directory.Exists(assetBundleDirectory))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
foreach (string file in Directory.GetFiles(assetBundleDirectory))
{
if (file.EndsWith(".manifest")) continue;
byte[] data = File.ReadAllBytes(file);
byte[] encryptedData = EncryptionUtils.Encrypt(data);
File.WriteAllBytes(file, encryptedData);
}
}
}
2. 加载解密的 Asset Bundle
在运行时加载并解密 Asset Bundle:
using UnityEngine;
using System.IO;
public class LoadEncryptedAssetBundles : MonoBehaviour
{
public string bundleName;
void Start()
{
string assetBundleDirectory = "Assets/AssetBundles";
string bundlePath = Path.Combine(assetBundleDirectory, bundleName);
if (File.Exists(bundlePath))
{
byte[] encryptedData = File.ReadAllBytes(bundlePath);
byte[] decryptedData = EncryptionUtils.Decrypt(encryptedData);
AssetBundle bundle = AssetBundle.LoadFromMemory(decryptedData);
if (bundle != null)
{
GameObject prefab = bundle.LoadAsset<GameObject>("YourPrefabName");
Instantiate(prefab);
bundle.Unload(false);
}
}
}
}