obfuz/Editor/EncryptionVM/VirtualMachineCodeGenerator.cs

205 lines
5.7 KiB
C#
Raw Normal View History

2025-05-11 17:36:58 +08:00
using Obfuz.Utils;
using System;
using System.Collections.Generic;
using System.IO;
2025-05-11 17:36:58 +08:00
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
2025-05-11 17:36:58 +08:00
using System.Threading.Tasks;
using UnityEngine;
2025-05-11 17:36:58 +08:00
namespace Obfuz.EncryptionVM
{
public class VirtualMachineCodeGenerator
{
private readonly int _opCodeCount;
private readonly int _opCodeBits;
private readonly VirtualMachine _vm;
2025-05-11 17:36:58 +08:00
public VirtualMachineCodeGenerator(string vmCodeGenerateSecretKey, int opCodeCount)
2025-05-11 17:36:58 +08:00
{
_opCodeCount = opCodeCount;
_opCodeBits = GetBitCount(opCodeCount - 1);
_vm = new VirtualMachineCreator(vmCodeGenerateSecretKey).CreateVirtualMachine(opCodeCount);
}
public VirtualMachineCodeGenerator(VirtualMachine vm)
{
_opCodeCount = vm.opCodes.Length;
_opCodeBits = GetBitCount(_opCodeCount - 1);
_vm = vm;
}
private static int GetBitCount(int value)
{
int count = 0;
while (value > 0)
{
count++;
value >>= 1;
}
return count;
}
public bool ValidateMatch(string outputFile)
{
if (!File.Exists(outputFile))
{
return false;
}
string oldCode = NormalizeText(File.ReadAllText(outputFile, Encoding.UTF8));
string newCode = NormalizeText(GenerateCode());
return oldCode == newCode;
}
private static string NormalizeText(string input)
{
return Regex.Replace(input, @"\s+", string.Empty);
2025-05-11 17:36:58 +08:00
}
public void Generate(string outputFile)
{
FileUtil.CreateParentDir(outputFile);
string code = GenerateCode();
File.WriteAllText(outputFile, code, Encoding.UTF8);
Debug.Log($"Generate EncryptionVM code to {outputFile}");
UnityEditor.AssetDatabase.Refresh();
}
private string GenerateCode()
{
var lines = new List<string>();
AppendHeader(lines);
AppendEncryptCodes(lines);
AppendDecryptCodes(lines);
AppendTailer(lines);
return string.Join("\n", lines);
}
private void AppendEncryptCodes(List<string> lines)
{
lines.Add(@"
private int ExecuteEncrypt(int value, int opCode, int salt)
{
switch (opCode)
{");
foreach (var opCode in _vm.opCodes)
{
lines.Add(@$" case {opCode.code}:
{{");
AppendEncryptCode(lines, opCode.function);
lines.Add(@"
return value;
}");
}
lines.Add(@"
default:
throw new System.Exception($""Invalid opCode:{opCode}"");
}
}");
}
private void AppendDecryptCodes(List<string> lines)
{
lines.Add(@"
private int ExecuteDecrypt(int value, int opCode, int salt)
{
switch (opCode)
{");
foreach (var opCode in _vm.opCodes)
{
lines.Add(@$" case {opCode.code}:
{{");
AppendDecryptCode(lines, opCode.function);
lines.Add(@"
return value;
}");
}
lines.Add(@"
default:
throw new System.Exception($""Invalid opCode:{opCode}"");
}
}");
}
private void AppendHeader(List<string> lines)
{
lines.Add($"/// This file is auto-generated by Obfuz. Do not modify it.");
lines.Add($"///");
//lines.Add($"/// Created Time: {DateTime.Now}");
lines.Add($"/// Version: {_vm.version}");
lines.Add($"/// SecretKey: {_vm.codeGenerationSecretKey}");
lines.Add($"/// OpCodeCount: {_vm.opCodes.Length}");
lines.Add(@"
namespace Obfuz.EncryptionVM
{
public class GeneratedEncryptionVirtualMachine : Obfuz.EncryptorBase
{");
lines.Add(@$"
private const int OpCodeBits = {_opCodeBits};
private const int OpCodeCount = {_opCodeCount};
private const int OpCodeMask = {_opCodeCount - 1};
");
lines.Add(@"
private readonly int[] _secretKey;
public GeneratedEncryptionVirtualMachine(byte[] secretKey)
{
this._secretKey = ConvertToIntKey(secretKey);
}
public override int Encrypt(int value, int opts, int salt)
{
while (opts > 0)
{
int opCode = opts & OpCodeMask;
value = ExecuteEncrypt(value, opCode, salt);
opts >>= OpCodeBits;
}
return value;
}
2025-05-11 17:36:58 +08:00
public override int Decrypt(int value, int opts, int salt)
{
while (opts > 0)
{
int opCode = opts & OpCodeMask;
value = ExecuteDecrypt(value, opCode, salt);
opts >>= OpCodeBits;
}
return value;
}
");
}
private void AppendTailer(List<string> lines)
{
lines.Add(@"
}
}
");
}
private void AppendEncryptCode(List<string> lines, IEncryptionInstruction instruction)
{
instruction.GenerateEncryptCode(lines, " ");
}
private void AppendDecryptCode(List<string> lines, IEncryptionInstruction instruction)
{
instruction.GenerateDecryptCode(lines, " ");
2025-05-11 17:36:58 +08:00
}
}
}