重构 Encryptor

backup
walon 2025-05-11 10:37:42 +08:00
parent 69e6068dd0
commit a7db16475a
17 changed files with 491 additions and 374 deletions

View File

@ -38,7 +38,7 @@ namespace Obfuz.Data
{ {
public FieldDef holderDataField; public FieldDef holderDataField;
public FieldDef runtimeValueField; public FieldDef runtimeValueField;
public long encryptionOps; public int encryptionOps;
public uint size; public uint size;
public List<byte> bytes; public List<byte> bytes;
public int salt; public int salt;
@ -134,7 +134,7 @@ namespace Obfuz.Data
runtimeValueField = runtimeValueField, runtimeValueField = runtimeValueField,
size = dataHolderType.ClassSize, size = dataHolderType.ClassSize,
bytes = new List<byte>((int)dataHolderType.ClassSize), bytes = new List<byte>((int)dataHolderType.ClassSize),
encryptionOps = _random.NextLong(), encryptionOps = _random.NextInt(),
salt = _random.NextInt(), salt = _random.NextInt(),
}; };
_rvaFields.Add(newRvaField); _rvaFields.Add(newRvaField);
@ -252,7 +252,7 @@ namespace Obfuz.Data
ins.Add(Instruction.Create(OpCodes.Call, importer.InitializedArrayMethod)); ins.Add(Instruction.Create(OpCodes.Call, importer.InitializedArrayMethod));
// EncryptionService.DecryptBlock(array, field.encryptionOps, field.salt); // EncryptionService.DecryptBlock(array, field.encryptionOps, field.salt);
ins.Add(Instruction.Create(OpCodes.Ldc_I8, field.encryptionOps)); ins.Add(Instruction.CreateLdcI4(field.encryptionOps));
ins.Add(Instruction.Create(OpCodes.Ldc_I4, field.salt)); ins.Add(Instruction.Create(OpCodes.Ldc_I4, field.salt));
ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptBlock)); ins.Add(Instruction.Create(OpCodes.Call, importer.DecryptBlock));

View File

@ -26,9 +26,9 @@ namespace Obfuz.Emit
Assert.IsNotNull(_initializeArray); Assert.IsNotNull(_initializeArray);
Type encryptionService = typeof(EncryptionService); Type encryptionService = typeof(EncryptionService);
_encryptBlock = mod.Import(encryptionService.GetMethod("EncryptBlock", new[] { typeof(byte[]), typeof(long), typeof(int) })); _encryptBlock = mod.Import(encryptionService.GetMethod("EncryptBlock", new[] { typeof(byte[]), typeof(int), typeof(int) }));
Assert.IsNotNull(_encryptBlock); Assert.IsNotNull(_encryptBlock);
_decryptBlock = mod.Import(encryptionService.GetMethod("DecryptBlock", new[] { typeof(byte[]), typeof(long), typeof(int) })); _decryptBlock = mod.Import(encryptionService.GetMethod("DecryptBlock", new[] { typeof(byte[]), typeof(int), typeof(int) }));
Assert.IsNotNull(_decryptBlock); Assert.IsNotNull(_decryptBlock);
_encryptInt = mod.Import(encryptionService.GetMethod("Encrypt", new[] { typeof(int), typeof(int), typeof(int) })); _encryptInt = mod.Import(encryptionService.GetMethod("Encrypt", new[] { typeof(int), typeof(int), typeof(int) }));
Assert.IsNotNull(_encryptInt); Assert.IsNotNull(_encryptInt);

View File

@ -1,257 +0,0 @@
using Obfuz.Utils;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Assertions;
using UnityEngine.UIElements;
namespace Obfuz.Encryption
{
public class VirtualMachine
{
public const int SecretKeyLength = 1024;
public readonly int vmSeed;
public readonly EncryptOpCode[] opCodes;
public VirtualMachine(int vmSeed, EncryptOpCode[] opCodes)
{
this.vmSeed = vmSeed;
this.opCodes = opCodes;
}
}
public interface IVirtualMachineCreator
{
VirtualMachine CreateVirtualMachine(int opCodeCount, int vmSeed);
}
public class RandomVirtualMachineCreator : IVirtualMachineCreator
{
private readonly int[] _debugSecretKey;
public RandomVirtualMachineCreator()
{
_debugSecretKey = new int[VirtualMachine.SecretKeyLength];
for (int i = 0; i < _debugSecretKey.Length; i++)
{
_debugSecretKey[i] = i;
}
}
private IEncryptInstruction CreateRandomInstruction(IRandom random, int secretKeyLength)
{
switch (random.NextInt(3))
{
case 0:
return new AddInstruction(random.NextInt(), random.NextInt(secretKeyLength));
case 1:
return new XorInstruction(random.NextInt(), random.NextInt(secretKeyLength));
case 2:
return new BitRotateInstruction(random.NextInt(32), random.NextInt(secretKeyLength));
default:
throw new System.Exception("Invalid instruction type");
}
}
private EncryptOpCode CreateEncryptOpCode(ushort code, IRandom r, int opCodeCount)
{
Assert.IsTrue(code < opCodeCount);
var insts = new IEncryptInstruction[opCodeCount];
for (int i = 0; i < insts.Length; i++)
{
IEncryptInstruction inst = CreateRandomInstruction(r, VirtualMachine.SecretKeyLength);
Assert.AreEqual(1234, inst.Decrypt(inst.Encrypt(1234, _debugSecretKey, i), _debugSecretKey, i));
insts[i] = CreateRandomInstruction(r, opCodeCount);
}
var function = new EncryptFunction(insts);
Assert.AreEqual(1234, function.Decrypt(function.Encrypt(1234, _debugSecretKey, code), _debugSecretKey, code));
return new EncryptOpCode(code, function);
}
public VirtualMachine CreateVirtualMachine(int opCodeCount, int vmSeed)
{
Assert.IsTrue(opCodeCount > 0);
Assert.AreEqual(0, opCodeCount ^ (opCodeCount - 1));
IRandom r = new RandomWithKey(new byte[] {1,2,3,4,5,6}, vmSeed);
var opCodes = new EncryptOpCode[opCodeCount];
for (int i = 0; i < opCodes.Length; i++)
{
opCodes[i] = CreateEncryptOpCode((ushort)i, r, opCodeCount);
}
return new VirtualMachine(vmSeed, opCodes);
}
}
public class EncryptVirtualMachineSimulator
{
private readonly EncryptOpCode[] _opCodes;
private readonly int[] _secretKey;
public EncryptVirtualMachineSimulator(EncryptOpCode[] opCodes, int[] secretKey)
{
_opCodes = opCodes;
// should be power of 2
Assert.AreEqual(0, opCodes.Length ^ (opCodes.Length - 1));
_secretKey = secretKey;
}
private List<ushort> DecodeOps(int ops)
{
var codes = new List<ushort>();
while (ops > 0)
{
var code = (ushort)(ops % _opCodes.Length);
codes.Add(code);
ops >>= 16;
}
return codes;
}
public int Encrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
foreach (var code in codes)
{
var opCode = _opCodes[code];
value = opCode.Encrypt(value, _secretKey, salt);
}
return value;
}
public int Decrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
for (int i = codes.Count - 1; i >= 0; i--)
{
var opCode = _opCodes[codes[i]];
value = opCode.Decrypt(value, _secretKey, salt);
}
return value;
}
public long Encrypt(long value, int ops, int salt)
{
int low = (int)(value & 0xFFFFFFFF);
int high = (int)((value >> 32) & 0xFFFFFFFF);
var codes = DecodeOps(ops);
// TODO we should encrypt high with encLow
int encLow = Encrypt(low, ops, salt);
int encHigh = Encrypt(high, ops, salt);
return ((long)encHigh << 32) | (long)(uint)(encLow);
}
public long Decrypt(long value, int ops, int salt)
{
int low = (int)(value & 0xFFFFFFFF);
int high = (int)((value >> 32) & 0xFFFFFFFF);
var codes = DecodeOps(ops);
// TODO we should encrypt high with encLow
int decLow = Decrypt(low, ops, salt);
int decHigh = Decrypt(high, ops, salt);
return ((long)decHigh << 32) | (long)(uint)(decLow);
}
public float Encrypt(float value, int ops, int salt)
{
int intValue = UnsafeUtility.As<float, int>(ref value);
int encValue = Encrypt(intValue, ops, salt);
return UnsafeUtility.As<int, float>(ref encValue);
}
public float Decrypt(float value, int ops, int salt)
{
int intValue = UnsafeUtility.As<float, int>(ref value);
int decValue = Decrypt(intValue, ops, salt);
return UnsafeUtility.As<int, float>(ref decValue);
}
public double Encrypt(double value, int ops, int salt)
{
long longValue = UnsafeUtility.As<double, long>(ref value);
long encValue = Encrypt(longValue, ops, salt);
return UnsafeUtility.As<long, double>(ref encValue);
}
public double Decrypt(double value, int ops, int salt)
{
long longValue = UnsafeUtility.As<double, long>(ref value);
long decValue = Decrypt(longValue, ops, salt);
return UnsafeUtility.As<long, double>(ref decValue);
}
public unsafe byte[] Encrypt(byte[] bytes, int offset, int length, int ops, int salt)
{
if (length == 0)
{
return Array.Empty<byte>();
}
// align size to 4
int align4Length = (length + 3) & ~3;
byte[] encInts = new byte[align4Length];
Buffer.BlockCopy(bytes, offset, encInts, 0, length);
int intLength = align4Length >> 2;
fixed (byte* intArr = &bytes[0])
{
for (int i = 0; i < intLength; i++)
{
int* ele = (int*)intArr + i;
*ele = Encrypt(*ele, ops, salt);
}
}
return encInts;
}
public unsafe byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt)
{
if (length == 0)
{
return Array.Empty<byte>();
}
int align4Length = (length + 3) & ~3;
int intLength = align4Length >> 2;
byte[] decInts = new byte[align4Length];
fixed (byte* intArr = &decInts[0])
{
for (int i = 0; i < intLength; i++)
{
int* ele = (int*)intArr + i;
*ele = Decrypt(*ele, ops, salt);
}
}
return decInts;
}
public byte[] Encrypt(byte[] bytes, int ops, int salt)
{
return Encrypt(bytes, 0, bytes.Length, ops, salt);
}
public byte[] Encrypt(string value, int ops, int salt)
{
if (value.Length == 0)
{
return Array.Empty<byte>();
}
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
return Encrypt(bytes, 0, bytes.Length, ops, salt);
}
public string DecryptString(byte[] value, int offset, int length, int ops, int salt)
{
if (length == 0)
{
return string.Empty;
}
return System.Text.Encoding.UTF8.GetString(Decrypt(value, offset, length, ops, salt));
}
}
}

View File

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Runtime.CompilerServices;
using System.Text;
using Unity.Collections.LowLevel.Unsafe;
using UnityEngine.Assertions;
using UnityEngine.UIElements;
namespace Obfuz.Encryption
{
public class EncryptionVirtualMachineSimulator : EncryptorBase
{
private readonly EncryptOpCode[] _opCodes;
private readonly int[] _secretKey;
public EncryptionVirtualMachineSimulator(EncryptOpCode[] opCodes, int[] secretKey)
{
_opCodes = opCodes;
// should be power of 2
Assert.AreEqual(0, opCodes.Length ^ (opCodes.Length - 1));
_secretKey = secretKey;
}
private List<ushort> DecodeOps(int ops)
{
var codes = new List<ushort>();
while (ops > 0)
{
var code = (ushort)(ops % _opCodes.Length);
codes.Add(code);
ops >>= 16;
}
return codes;
}
public override int Encrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
foreach (var code in codes)
{
var opCode = _opCodes[code];
value = opCode.Encrypt(value, _secretKey, salt);
}
return value;
}
public override int Decrypt(int value, int ops, int salt)
{
var codes = DecodeOps(ops);
for (int i = codes.Count - 1; i >= 0; i--)
{
var opCode = _opCodes[codes[i]];
value = opCode.Decrypt(value, _secretKey, salt);
}
return value;
}
}
}

View File

@ -0,0 +1,7 @@
namespace Obfuz.Encryption
{
public interface IVirtualMachineCreator
{
VirtualMachine CreateVirtualMachine(int opCodeCount, int vmSeed);
}
}

View File

@ -0,0 +1,62 @@
using Obfuz.Utils;
using UnityEngine.Assertions;
namespace Obfuz.Encryption
{
public class RandomVirtualMachineCreator : IVirtualMachineCreator
{
private readonly int[] _debugSecretKey;
public RandomVirtualMachineCreator()
{
_debugSecretKey = new int[VirtualMachine.SecretKeyLength];
for (int i = 0; i < _debugSecretKey.Length; i++)
{
_debugSecretKey[i] = i;
}
}
private IEncryptInstruction CreateRandomInstruction(IRandom random, int secretKeyLength)
{
switch (random.NextInt(3))
{
case 0:
return new AddInstruction(random.NextInt(), random.NextInt(secretKeyLength));
case 1:
return new XorInstruction(random.NextInt(), random.NextInt(secretKeyLength));
case 2:
return new BitRotateInstruction(random.NextInt(32), random.NextInt(secretKeyLength));
default:
throw new System.Exception("Invalid instruction type");
}
}
private EncryptOpCode CreateEncryptOpCode(ushort code, IRandom r, int opCodeCount)
{
Assert.IsTrue(code < opCodeCount);
var insts = new IEncryptInstruction[opCodeCount];
for (int i = 0; i < insts.Length; i++)
{
IEncryptInstruction inst = CreateRandomInstruction(r, VirtualMachine.SecretKeyLength);
Assert.AreEqual(1234, inst.Decrypt(inst.Encrypt(1234, _debugSecretKey, i), _debugSecretKey, i));
insts[i] = CreateRandomInstruction(r, opCodeCount);
}
var function = new EncryptFunction(insts);
Assert.AreEqual(1234, function.Decrypt(function.Encrypt(1234, _debugSecretKey, code), _debugSecretKey, code));
return new EncryptOpCode(code, function);
}
public VirtualMachine CreateVirtualMachine(int opCodeCount, int vmSeed)
{
Assert.IsTrue(opCodeCount > 0);
Assert.AreEqual(0, opCodeCount ^ (opCodeCount - 1));
IRandom r = new RandomWithKey(new byte[] {1,2,3,4,5,6}, vmSeed);
var opCodes = new EncryptOpCode[opCodeCount];
for (int i = 0; i < opCodes.Length; i++)
{
opCodes[i] = CreateEncryptOpCode((ushort)i, r, opCodeCount);
}
return new VirtualMachine(vmSeed, opCodes);
}
}
}

View File

@ -0,0 +1,16 @@
namespace Obfuz.Encryption
{
public class VirtualMachine
{
public const int SecretKeyLength = 1024;
public readonly int vmSeed;
public readonly EncryptOpCode[] opCodes;
public VirtualMachine(int vmSeed, EncryptOpCode[] opCodes)
{
this.vmSeed = vmSeed;
this.opCodes = opCodes;
}
}
}

View File

@ -68,7 +68,7 @@ namespace Obfuz
var random = new RandomWithKey(_secretKey, _globalRandomSeed); var random = new RandomWithKey(_secretKey, _globalRandomSeed);
var encryptor = new DefaultEncryptor(_secretKey); var encryptor = new NullEncryptor(_secretKey);
var rvaDataAllocator = new RvaDataAllocator(random, encryptor); var rvaDataAllocator = new RvaDataAllocator(random, encryptor);
var constFieldAllocator = new ConstFieldAllocator(encryptor, random, rvaDataAllocator); var constFieldAllocator = new ConstFieldAllocator(encryptor, random, rvaDataAllocator);
_ctx = new ObfuscationPassContext _ctx = new ObfuscationPassContext

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace Obfuz.Settings
{
[Serializable]
public class EncryptionVMSettings
{
[Tooltip("secret key for generating encryption virtual machine source code")]
public string codeGenerationSecretKey = "Obfuz";
[Tooltip("encryption virtual machine source code output dir")]
public string codeOutputDir = "Assets/Obfuz";
}
}

View File

@ -32,6 +32,9 @@ namespace Obfuz.Settings
[Tooltip("global random seed")] [Tooltip("global random seed")]
public int globalRandomSeed = 0; public int globalRandomSeed = 0;
[Tooltip("encryption virtual machine settings")]
public EncryptionVMSettings encryptionVMSettings;
[Tooltip("symbol obfuscation settings")] [Tooltip("symbol obfuscation settings")]
public SymbolObfusSettings symbolObfusSettings; public SymbolObfusSettings symbolObfusSettings;

View File

@ -36,6 +36,8 @@ namespace Obfuz.Settings
private SerializedProperty _enabledObfuscationPasses; private SerializedProperty _enabledObfuscationPasses;
private SerializedProperty _secretKey; private SerializedProperty _secretKey;
private SerializedProperty _globalRandomSeed; private SerializedProperty _globalRandomSeed;
private SerializedProperty _encryptionVMSettings;
private SerializedProperty _symbolObfusSettings; private SerializedProperty _symbolObfusSettings;
private SerializedProperty _constEncryptSettings; private SerializedProperty _constEncryptSettings;
@ -71,6 +73,8 @@ namespace Obfuz.Settings
_secretKey = _serializedObject.FindProperty("secretKey"); _secretKey = _serializedObject.FindProperty("secretKey");
_globalRandomSeed = _serializedObject.FindProperty("globalRandomSeed"); _globalRandomSeed = _serializedObject.FindProperty("globalRandomSeed");
_encryptionVMSettings = _serializedObject.FindProperty("encryptionVMSettings");
_symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings"); _symbolObfusSettings = _serializedObject.FindProperty("symbolObfusSettings");
_constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings"); _constEncryptSettings = _serializedObject.FindProperty("constEncryptSettings");
_fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings"); _fieldEncryptSettings = _serializedObject.FindProperty("fieldEncryptSettings");
@ -95,6 +99,8 @@ namespace Obfuz.Settings
EditorGUILayout.PropertyField(_secretKey); EditorGUILayout.PropertyField(_secretKey);
EditorGUILayout.PropertyField(_globalRandomSeed); EditorGUILayout.PropertyField(_globalRandomSeed);
EditorGUILayout.PropertyField(_encryptionVMSettings);
EditorGUILayout.PropertyField(_symbolObfusSettings); EditorGUILayout.PropertyField(_symbolObfusSettings);
EditorGUILayout.PropertyField(_constEncryptSettings); EditorGUILayout.PropertyField(_constEncryptSettings);
EditorGUILayout.PropertyField(_fieldEncryptSettings); EditorGUILayout.PropertyField(_fieldEncryptSettings);

View File

@ -15,7 +15,7 @@ namespace Obfuz.Settings
[Tooltip("prefix for obfuscated name to avoid name confliction with original name")] [Tooltip("prefix for obfuscated name to avoid name confliction with original name")]
public string obfuscatedNamePrefix = "$"; public string obfuscatedNamePrefix = "$";
[Tooltip("obfuscate same namespace to same name")] [Tooltip("obfuscate same namespace to one name")]
public bool useConsistentNamespaceObfuscation = true; public bool useConsistentNamespaceObfuscation = true;
[Tooltip("path of mapping.xml")] [Tooltip("path of mapping.xml")]

View File

@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz
{
public class DefaultEncryptor : IEncryptor
{
private readonly byte[] _key;
public DefaultEncryptor(byte[] key)
{
_key = key;
}
public void EncryptBlock(byte[] data, long ops, int salt)
{
for (int i = 0; i < data.Length; i++)
{
data[i] ^= (byte)(_key[i % _key.Length] ^ salt);
}
}
public void DecryptBlock(byte[] data, long ops, int salt)
{
for (int i = 0; i < data.Length; i++)
{
data[i] ^= (byte)(_key[i % _key.Length] ^ salt);
}
}
public int Encrypt(int value, int opts, int salt)
{
return value;
}
public int Decrypt(int value, int opts, int salt)
{
return value;
}
public long Encrypt(long value, int opts, int salt)
{
return value;
}
public long Decrypt(long value, int opts, int salt)
{
return value;
}
public float Encrypt(float value, int opts, int salt)
{
return value;
}
public float Decrypt(float value, int opts, int salt)
{
return value;
}
public double Encrypt(double value, int opts, int salt)
{
return value;
}
public double Decrypt(double value, int opts, int salt)
{
return value;
}
public byte[] Encrypt(byte[] value, int offset, int length, int opts, int salt)
{
int align4Length = (length + 3) & ~3;
var encryptedBytes = new byte[align4Length];
Buffer.BlockCopy(value, offset, encryptedBytes, 0, length);
return encryptedBytes;
}
public byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt)
{
byte[] byteArr = new byte[length];
Buffer.BlockCopy(value, 0, byteArr, 0, length);
return byteArr;
}
public byte[] Encrypt(string value, int ops, int salt)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
return Encrypt(bytes, 0, bytes.Length, ops, salt);
}
public string DecryptString(byte[] value, int offset, int length, int ops, int salt)
{
byte[] bytes = new byte[length];
Buffer.BlockCopy(value, 0, bytes, 0, length);
return Encoding.UTF8.GetString(bytes);
}
}
}

View File

@ -8,14 +8,14 @@ namespace Obfuz
{ {
public static class EncryptionService public static class EncryptionService
{ {
private static readonly IEncryptor _encryptor = new DefaultEncryptor(new byte[] { 0x1A, 0x2B, 0x3C, 0x4D }); private static readonly IEncryptor _encryptor = new NullEncryptor(new byte[] { 0x1A, 0x2B, 0x3C, 0x4D });
public static void EncryptBlock(byte[] data, long ops, int salt) public static void EncryptBlock(byte[] data, int ops, int salt)
{ {
_encryptor.EncryptBlock(data, ops, salt); _encryptor.EncryptBlock(data, ops, salt);
} }
public static void DecryptBlock(byte[] data, long ops, int salt) public static void DecryptBlock(byte[] data, int ops, int salt)
{ {
_encryptor.DecryptBlock(data, ops, salt); _encryptor.DecryptBlock(data, ops, salt);
} }

215
Runtime/EncryptorBase.cs Normal file
View File

@ -0,0 +1,215 @@
using System;
using System.Text;
using Unity.Collections.LowLevel.Unsafe;
namespace Obfuz
{
public abstract class EncryptorBase : IEncryptor
{
public abstract int Encrypt(int value, int opts, int salt);
public abstract int Decrypt(int value, int opts, int salt);
public virtual long Encrypt(long value, int opts, int salt)
{
int low = (int)value;
int high = (int)(value >> 32);
int encryptedLow = Encrypt(low, opts, salt);
int encryptedHigh = Encrypt(high, opts, salt);
return ((long)encryptedHigh << 32) | (uint)encryptedLow;
}
public virtual long Decrypt(long value, int opts, int salt)
{
int low = (int)value;
int high = (int)(value >> 32);
int decryptedLow = Decrypt(low, opts, salt);
int decryptedHigh = Decrypt(high, opts, salt);
return ((long)decryptedHigh << 32) | (uint)decryptedLow;
}
public virtual float Encrypt(float value, int opts, int salt)
{
ref int intValue = ref UnsafeUtility.As<float, int>(ref value);
intValue = Encrypt(intValue, opts, salt);
return value;
}
public virtual float Decrypt(float value, int opts, int salt)
{
ref int intValue = ref UnsafeUtility.As<float, int>(ref value);
intValue = Decrypt(intValue, opts, salt);
return value;
}
public virtual double Encrypt(double value, int opts, int salt)
{
ref long longValue = ref UnsafeUtility.As<double, long>(ref value);
longValue = Encrypt(longValue, opts, salt);
return value;
}
public virtual double Decrypt(double value, int opts, int salt)
{
ref long longValue = ref UnsafeUtility.As<double, long>(ref value);
longValue = Decrypt(longValue, opts, salt);
return value;
}
public virtual unsafe byte[] Encrypt(byte[] value, int offset, int length, int ops, int salt)
{
if (length == 0)
{
return Array.Empty<byte>();
}
var encryptedBytes = new byte[length];
int intArrLength = length >> 2;
// align to 4
if ((offset & 0x3) != 0)
{
Buffer.BlockCopy(value, offset, encryptedBytes, 0, length);
// encrypt int
fixed (byte* dstBytePtr = &encryptedBytes[0])
{
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Encrypt(dstIntPtr[i], ops, salt);
}
}
for (int i = intArrLength * 4; i < length; i++)
{
encryptedBytes[i] = (byte)(encryptedBytes[i] ^ salt);
}
}
else
{
// encrypt int
fixed (byte* srcBytePtr = &value[offset])
{
fixed (byte* dstBytePtr = &encryptedBytes[0])
{
int* srcIntPtr = (int*)srcBytePtr;
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Encrypt(srcIntPtr[i], ops, salt);
}
}
}
for (int i = intArrLength * 4; i < length; i++)
{
encryptedBytes[i] = (byte)(value[offset + i] ^ salt);
}
}
return encryptedBytes;
}
public unsafe virtual byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt)
{
var decryptedBytes = new byte[length];
int intArrLength = length >> 2;
// align to 4
if ((offset & 0x3) != 0)
{
Buffer.BlockCopy(value, offset, decryptedBytes, 0, length);
// encrypt int
fixed (byte* dstBytePtr = &decryptedBytes[0])
{
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Decrypt(dstIntPtr[i], ops, salt);
}
}
for (int i = intArrLength * 4; i < length; i++)
{
decryptedBytes[i] = (byte)(decryptedBytes[i] ^ salt);
}
}
else
{
// encrypt int
fixed (byte* srcBytePtr = &value[offset])
{
fixed (byte* dstBytePtr = &decryptedBytes[0])
{
int* srcIntPtr = (int*)srcBytePtr;
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Decrypt(srcIntPtr[i], ops, salt);
}
}
}
for (int i = intArrLength * 4; i < length; i++)
{
decryptedBytes[i] = (byte)(value[offset + i] ^ salt);
}
}
return decryptedBytes;
}
public virtual byte[] Encrypt(string value, int ops, int salt)
{
byte[] bytes = Encoding.UTF8.GetBytes(value);
return Encrypt(bytes, 0, bytes.Length, ops, salt);
}
public virtual string DecryptString(byte[] value, int offset, int length, int ops, int salt)
{
byte[] bytes = Decrypt(value, offset, length, ops, salt);
return Encoding.UTF8.GetString(bytes);
}
public virtual unsafe void EncryptBlock(byte[] data, int ops, int salt)
{
int length = data.Length;
int intArrLength = length >> 2;
fixed (byte* dstBytePtr = &data[0])
{
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Encrypt(dstIntPtr[i], ops, salt);
}
}
for (int i = intArrLength * 4; i < length; i++)
{
data[i] = (byte)(data[i] ^ salt);
}
}
public virtual unsafe void DecryptBlock(byte[] data, int ops, int salt)
{
int length = data.Length;
int intArrLength = length >> 2;
fixed (byte* dstBytePtr = &data[0])
{
int* dstIntPtr = (int*)dstBytePtr;
for (int i = 0; i < intArrLength; i++)
{
dstIntPtr[i] = Decrypt(dstIntPtr[i], ops, salt);
}
}
for (int i = intArrLength * 4; i < length; i++)
{
data[i] = (byte)(data[i] ^ salt);
}
}
}
}

View File

@ -1,15 +1,13 @@
using System; using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Obfuz namespace Obfuz
{ {
public interface IEncryptor public interface IEncryptor
{ {
void EncryptBlock(byte[] data, long ops, int salt); void EncryptBlock(byte[] data, int ops, int salt);
void DecryptBlock(byte[] data, long ops, int salt); void DecryptBlock(byte[] data, int ops, int salt);
int Encrypt(int value, int opts, int salt); int Encrypt(int value, int opts, int salt);
int Decrypt(int value, int opts, int salt); int Decrypt(int value, int opts, int salt);

90
Runtime/NullEncryptor.cs Normal file
View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Obfuz
{
public class NullEncryptor : EncryptorBase
{
private readonly byte[] _key;
public NullEncryptor(byte[] key)
{
_key = key;
}
public override int Encrypt(int value, int opts, int salt)
{
return value;
}
public override int Decrypt(int value, int opts, int salt)
{
return value;
}
public override long Encrypt(long value, int opts, int salt)
{
return value;
}
public override long Decrypt(long value, int opts, int salt)
{
return value;
}
public override float Encrypt(float value, int opts, int salt)
{
return value;
}
public override float Decrypt(float value, int opts, int salt)
{
return value;
}
public override double Encrypt(double value, int opts, int salt)
{
return value;
}
public override double Decrypt(double value, int opts, int salt)
{
return value;
}
public override byte[] Encrypt(byte[] value, int offset, int length, int opts, int salt)
{
if (length == 0)
{
return Array.Empty<byte>();
}
var encryptedBytes = new byte[length];
Buffer.BlockCopy(value, offset, encryptedBytes, 0, length);
return encryptedBytes;
}
public override byte[] Decrypt(byte[] value, int offset, int length, int ops, int salt)
{
if (length == 0)
{
return Array.Empty<byte>();
}
byte[] byteArr = new byte[length];
Buffer.BlockCopy(value, 0, byteArr, 0, length);
return byteArr;
}
public override byte[] Encrypt(string value, int ops, int salt)
{
return Encoding.UTF8.GetBytes(value);
}
public override string DecryptString(byte[] value, int offset, int length, int ops, int salt)
{
return Encoding.UTF8.GetString(value, offset, length);
}
}
}