EncryptionVM
parent
ebce42a8d6
commit
5e45a684aa
|
@ -0,0 +1,118 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Obfuz.Encryption
|
||||||
|
{
|
||||||
|
public interface IEncryptInstruction
|
||||||
|
{
|
||||||
|
int Encrypt(int value, int[] secretKey, int salt);
|
||||||
|
|
||||||
|
int Decrypt(int value, int[] secretKey, int salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract class EncryptInstructionBase : IEncryptInstruction
|
||||||
|
{
|
||||||
|
public abstract int Encrypt(int value, int[] secretKey, int salt);
|
||||||
|
public abstract int Decrypt(int value, int[] secretKey, int salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddInstruction : EncryptInstructionBase
|
||||||
|
{
|
||||||
|
private readonly int _addValue;
|
||||||
|
private readonly int _opKeyIndex;
|
||||||
|
|
||||||
|
public AddInstruction(int addValue, int opKeyIndex)
|
||||||
|
{
|
||||||
|
_addValue = addValue;
|
||||||
|
_opKeyIndex = opKeyIndex;
|
||||||
|
}
|
||||||
|
public override int Encrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return value + secretKey[_opKeyIndex] + salt + _addValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Decrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return value - secretKey[_opKeyIndex] - salt - _addValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class XorInstruction : EncryptInstructionBase
|
||||||
|
{
|
||||||
|
private readonly int _xorValue;
|
||||||
|
private readonly int _opKeyIndex;
|
||||||
|
|
||||||
|
public XorInstruction(int xorValue, int opKeyIndex)
|
||||||
|
{
|
||||||
|
_xorValue = xorValue;
|
||||||
|
_opKeyIndex = opKeyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Encrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return value ^ secretKey[_opKeyIndex] ^ salt ^ _xorValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Decrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return value ^ secretKey[_opKeyIndex] ^ salt ^ _xorValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BitRotateInstruction : EncryptInstructionBase
|
||||||
|
{
|
||||||
|
private readonly int _rotateBitNum;
|
||||||
|
private readonly int _opKeyIndex;
|
||||||
|
|
||||||
|
public BitRotateInstruction(int rotateBitNum, int opKeyIndex)
|
||||||
|
{
|
||||||
|
_rotateBitNum = rotateBitNum;
|
||||||
|
_opKeyIndex = opKeyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Encrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
uint part1 = (uint)value << _rotateBitNum;
|
||||||
|
uint part2 = (uint)value >> (32 - _rotateBitNum);
|
||||||
|
return ((int)(part1 | part2) ^ secretKey[_opKeyIndex]) + salt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Decrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
uint value2 = (uint)((value - salt) ^ secretKey[_opKeyIndex]);
|
||||||
|
uint part1 = value2 >> _rotateBitNum;
|
||||||
|
uint part2 = value2 << (32 - _rotateBitNum);
|
||||||
|
return (int)(part1 | part2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class EncryptFunction : EncryptInstructionBase
|
||||||
|
{
|
||||||
|
private readonly IEncryptInstruction[] _instructions;
|
||||||
|
|
||||||
|
public EncryptFunction(IEncryptInstruction[] instructions)
|
||||||
|
{
|
||||||
|
_instructions = instructions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Encrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
foreach (var instruction in _instructions)
|
||||||
|
{
|
||||||
|
value = instruction.Encrypt(value, secretKey, salt);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Decrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
for (int i = _instructions.Length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
value = _instructions[i].Decrypt(value, secretKey, salt);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
namespace Obfuz.Encryption
|
||||||
|
{
|
||||||
|
public class EncryptOpCode
|
||||||
|
{
|
||||||
|
public readonly ushort code;
|
||||||
|
|
||||||
|
public readonly EncryptFunction function;
|
||||||
|
|
||||||
|
public EncryptOpCode(ushort code, EncryptFunction function)
|
||||||
|
{
|
||||||
|
this.code = code;
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Encrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return function.Encrypt(value, secretKey, salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Decrypt(int value, int[] secretKey, int salt)
|
||||||
|
{
|
||||||
|
return function.Decrypt(value, secretKey, salt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
using Obfuz.Utils;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
using Unity.Collections.LowLevel.Unsafe;
|
||||||
|
using UnityEngine.Assertions;
|
||||||
|
|
||||||
|
namespace Obfuz.Encryption
|
||||||
|
{
|
||||||
|
public class VirtualMachine
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
public RandomVirtualMachineCreator()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEncryptInstruction CreateRandomInstruction(IRandom random, int opCodeCount)
|
||||||
|
{
|
||||||
|
switch (random.NextInt(3))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return new AddInstruction(random.NextInt(), random.NextInt(opCodeCount));
|
||||||
|
case 1:
|
||||||
|
return new XorInstruction(random.NextInt(), random.NextInt(opCodeCount));
|
||||||
|
case 2:
|
||||||
|
return new BitRotateInstruction(random.NextInt(32), random.NextInt(opCodeCount));
|
||||||
|
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++)
|
||||||
|
{
|
||||||
|
insts[i] = CreateRandomInstruction(r, opCodeCount);
|
||||||
|
}
|
||||||
|
var function = new EncryptFunction(insts);
|
||||||
|
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 int[] Encrypt(byte[] bytes, int offset, int length, int ops, int salt)
|
||||||
|
{
|
||||||
|
if (length == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<int>();
|
||||||
|
}
|
||||||
|
int intLength = (length + 3) / 4;
|
||||||
|
int[] encInts = new int[intLength];
|
||||||
|
Buffer.BlockCopy(bytes, offset, encInts, 0, length);
|
||||||
|
for (int i = 0; i < intLength; i++)
|
||||||
|
{
|
||||||
|
encInts[i] = Encrypt(encInts[i], ops, salt);
|
||||||
|
}
|
||||||
|
return encInts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] Decrypt(int[] value, int offset, int byteLength, int ops, int salt)
|
||||||
|
{
|
||||||
|
if (byteLength == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<byte>();
|
||||||
|
}
|
||||||
|
int intLength = (byteLength + 3) / 4;
|
||||||
|
int[] decValue = new int[intLength];
|
||||||
|
for (int i = 0; i < intLength; i++)
|
||||||
|
{
|
||||||
|
decValue[i] = Decrypt(value[i], ops, salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = new byte[byteLength];
|
||||||
|
Buffer.BlockCopy(decValue, 0, bytes, 0, byteLength);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int[] Encrypt(string value, int ops, int salt)
|
||||||
|
{
|
||||||
|
if (value.Length == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<int>();
|
||||||
|
}
|
||||||
|
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(value);
|
||||||
|
return Encrypt(bytes, 0, bytes.Length, ops, salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DecryptString(int[] value, int offset, int stringBytesLength, int ops, int salt)
|
||||||
|
{
|
||||||
|
if (stringBytesLength == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
int intLength = (stringBytesLength + 3) / 4;
|
||||||
|
int[] intValue = new int[intLength];
|
||||||
|
for (int i = 0; i < intLength; i++)
|
||||||
|
{
|
||||||
|
intValue[i] = Decrypt(value[i], ops, salt);
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = new byte[stringBytesLength];
|
||||||
|
Buffer.BlockCopy(intValue, 0, bytes, 0, stringBytesLength);
|
||||||
|
return System.Text.Encoding.UTF8.GetString(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Obfuz.Encryption
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using dnlib.DotNet;
|
using dnlib.DotNet;
|
||||||
using dnlib.DotNet.Emit;
|
using dnlib.DotNet.Emit;
|
||||||
|
using Obfuz.ObfusPasses.ConstObfus.Policies;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
@ -13,7 +14,7 @@ namespace Obfuz.ObfusPasses.ConstObfus
|
||||||
|
|
||||||
public class ConstObfusPass : InstructionObfuscationPassBase
|
public class ConstObfusPass : InstructionObfuscationPassBase
|
||||||
{
|
{
|
||||||
private IConstObfuscationPolicy _dataObfuscatorPolicy;
|
private IObfuscationPolicy _dataObfuscatorPolicy;
|
||||||
private IDataObfuscator _dataObfuscator;
|
private IDataObfuscator _dataObfuscator;
|
||||||
|
|
||||||
public override void Start(ObfuscationPassContext ctx)
|
public override void Start(ObfuscationPassContext ctx)
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
using dnlib.DotNet;
|
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.ConstObfus
|
|
||||||
{
|
|
||||||
public abstract class ConstObfuscationPolicyBase : IConstObfuscationPolicy
|
|
||||||
{
|
|
||||||
public virtual bool NeedObfuscateMethod(MethodDef method)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateInt(MethodDef method, int value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateLong(MethodDef method, long value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateFloat(MethodDef method, float value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateDouble(MethodDef method, double value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateString(MethodDef method, string value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool NeedObfuscateArray(MethodDef method, byte[] array)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,7 +7,6 @@ namespace Obfuz.ObfusPasses.ConstObfus
|
||||||
{
|
{
|
||||||
public interface IDataObfuscator
|
public interface IDataObfuscator
|
||||||
{
|
{
|
||||||
|
|
||||||
void ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions);
|
void ObfuscateInt(MethodDef method, int value, List<Instruction> obfuscatedInstructions);
|
||||||
|
|
||||||
void ObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions);
|
void ObfuscateLong(MethodDef method, long value, List<Instruction> obfuscatedInstructions);
|
||||||
|
|
|
@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.ConstObfus
|
namespace Obfuz.ObfusPasses.ConstObfus
|
||||||
{
|
{
|
||||||
public interface IConstObfuscationPolicy
|
public interface IObfuscationPolicy
|
||||||
{
|
{
|
||||||
bool NeedObfuscateMethod(MethodDef method);
|
bool NeedObfuscateMethod(MethodDef method);
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
using dnlib.DotNet;
|
||||||
|
|
||||||
|
namespace Obfuz.ObfusPasses.ConstObfus.Policies
|
||||||
|
{
|
||||||
|
public abstract class ObfuscationPolicyBase : IObfuscationPolicy
|
||||||
|
{
|
||||||
|
public abstract bool NeedObfuscateArray(MethodDef method, byte[] array);
|
||||||
|
public abstract bool NeedObfuscateDouble(MethodDef method, double value);
|
||||||
|
public abstract bool NeedObfuscateFloat(MethodDef method, float value);
|
||||||
|
public abstract bool NeedObfuscateInt(MethodDef method, int value);
|
||||||
|
public abstract bool NeedObfuscateLong(MethodDef method, long value);
|
||||||
|
public abstract bool NeedObfuscateMethod(MethodDef method);
|
||||||
|
public abstract bool NeedObfuscateString(MethodDef method, string value);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,9 +5,9 @@ using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Obfuz.ObfusPasses.ConstObfus
|
namespace Obfuz.ObfusPasses.ConstObfus.Policies
|
||||||
{
|
{
|
||||||
public class RuleBasedObfuscationPolicy : ConstObfuscationPolicyBase
|
public class RuleBasedObfuscationPolicy : ObfuscationPolicyBase
|
||||||
{
|
{
|
||||||
public override bool NeedObfuscateMethod(MethodDef method)
|
public override bool NeedObfuscateMethod(MethodDef method)
|
||||||
{
|
{
|
|
@ -9,26 +9,21 @@ namespace Obfuz.Utils
|
||||||
{
|
{
|
||||||
public class RandomWithKey : IRandom
|
public class RandomWithKey : IRandom
|
||||||
{
|
{
|
||||||
|
// LCG 参数(使用经典的数值)
|
||||||
|
private const long a = 1664525;
|
||||||
|
private const long c = 1013904223;
|
||||||
|
private const long m = 4294967296; // 2^32
|
||||||
|
|
||||||
private readonly byte[] _key;
|
private readonly byte[] _key;
|
||||||
|
|
||||||
private readonly Random _random;
|
|
||||||
|
|
||||||
private int _nextIndex;
|
private int _nextIndex;
|
||||||
|
|
||||||
|
private int _seed;
|
||||||
|
|
||||||
public RandomWithKey(byte[] key, int seed)
|
public RandomWithKey(byte[] key, int seed)
|
||||||
{
|
{
|
||||||
_key = key;
|
_key = key;
|
||||||
// TODO use key and seed to generate a random number
|
_seed = seed;
|
||||||
_random = new Random(GenerateSeed(key, seed));
|
|
||||||
}
|
|
||||||
|
|
||||||
private int GenerateSeed(byte[] key, int seed)
|
|
||||||
{
|
|
||||||
foreach (var b in key)
|
|
||||||
{
|
|
||||||
seed = seed * 31 + b;
|
|
||||||
}
|
|
||||||
return seed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int NextInt(int min, int max)
|
public int NextInt(int min, int max)
|
||||||
|
@ -52,7 +47,8 @@ namespace Obfuz.Utils
|
||||||
|
|
||||||
public int NextInt()
|
public int NextInt()
|
||||||
{
|
{
|
||||||
return _random.Next() ^ GetNextKeyByte();
|
_seed = (int)((a * _seed + c) % m);
|
||||||
|
return _seed ^ GetNextKeyByte();
|
||||||
}
|
}
|
||||||
|
|
||||||
public long NextLong()
|
public long NextLong()
|
||||||
|
|
Loading…
Reference in New Issue