diff --git a/Tests/TestApp/Program.cs b/Tests/TestApp/Program.cs index 89f88dc..0599e9e 100644 --- a/Tests/TestApp/Program.cs +++ b/Tests/TestApp/Program.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Concurrent; -using System.Linq; -using System.Reflection; using ZeroLevel.Logging; -using ZeroLevel.Services.Invokation; -using ZeroLevel.Services.Serialization; +using ZeroLevel.Services.HashFunctions; +using ZeroLevel.Services.Mathemathics; namespace TestApp { @@ -54,10 +52,34 @@ namespace TestApp internal static class Program { - - private static void Main(string[] args) { + var date = DateTime.Now; + + var bytes = new byte[1531]; + new Random().NextBytes(bytes); + var hash = Murmur3.ComputeULongHash(bytes); + Console.WriteLine($"{hash}"); + + new Random().NextBytes(bytes); + hash = Murmur3.ComputeULongHash(bytes); + Console.WriteLine($"{hash}"); + + bytes[0] = 10; + hash = Murmur3.ComputeULongHash(bytes); + Console.WriteLine($"{hash}"); + + new Random().NextBytes(bytes); + hash = Murmur3.ComputeULongHash(bytes); + Console.WriteLine($"{hash}"); + Console.ReadKey(); + + /* + foreach (var c in Combinations.GenerateUniqueSets(new int[] { 1, 2, 3, 4, 5, 6 }, 3)) + { + Console.WriteLine(string.Join('\t', c)); + } + */ } } } \ No newline at end of file diff --git a/Tests/TestApp/t.cs b/Tests/TestApp/t.cs new file mode 100644 index 0000000..c7da7f3 --- /dev/null +++ b/Tests/TestApp/t.cs @@ -0,0 +1,27 @@ +using System; +using System.Linq; + +namespace TestApp +{ + internal class t + { + public int Calculate() + { + var c = int.Parse(Console.ReadLine()); + var data = Console.ReadLine().Split(' ').Select(s => int.Parse(s)).ToArray(); + int result = 0; + for (int i = 0; i < c - 1; i++) + { + for (int j = i + 1; j < c; j++) + { + var d1 = Math.Min(data[i], data[j]); + var d2 = Math.Max(data[i], data[j]); + if (d2 > 100000) continue; + if ((d1 != 0 && d2 != 0) && ((float)d1 / d2) >= .9f) + result++; + } + } + return result; + } + } +} diff --git a/Tests/ZeroLevel.UnitTests/BytesEncodingTest.cs b/Tests/ZeroLevel.UnitTests/BytesEncodingTest.cs new file mode 100644 index 0000000..2f0f1cf --- /dev/null +++ b/Tests/ZeroLevel.UnitTests/BytesEncodingTest.cs @@ -0,0 +1,110 @@ +using System; +using Xunit; + +namespace ZeroLevel.UnitTests +{ + public class BytesEncodingTests + { + public static void DeHashData(byte[] data, byte initialMask) + { + int i; + for (i = data.Length - 1; i > 9; i -= 8) + { + data[i - 0] ^= data[i - 1]; + data[i - 1] ^= data[i - 2]; + data[i - 2] ^= data[i - 3]; + data[i - 3] ^= data[i - 4]; + data[i - 4] ^= data[i - 5]; + data[i - 5] ^= data[i - 6]; + data[i - 6] ^= data[i - 7]; + data[i - 7] ^= data[i - 8]; + } + for (; i >= 1; i--) + { + data[i] ^= data[i - 1]; + } + data[0] ^= initialMask; + } + + public static void HashData(byte[] data, byte initialmask) + { + if (data == null || data.Length == 0) return; + int i = 1; + data[0] ^= initialmask; + for (; i < (data.Length - 8); i += 8) + { + data[i + 0] ^= data[i - 1]; + data[i + 1] ^= data[i + 0]; + data[i + 2] ^= data[i + 1]; + data[i + 3] ^= data[i + 2]; + data[i + 4] ^= data[i + 3]; + data[i + 5] ^= data[i + 4]; + data[i + 6] ^= data[i + 5]; + data[i + 7] ^= data[i + 6]; + } + for (; i < data.Length; i++) + { + data[i] ^= data[i - 1]; + } + } + + [Fact] + public void SpecialTest() + { + var arr = new byte[] { 244, 135 }; //, 125, 160, 109, 144, 187, 109, 88, 78, 175, 115, 83, 174, 165, 246, 253, 112 }; + var copy = new byte[arr.Length]; + Array.Copy(arr, copy, arr.Length); + + byte initial = (byte)(arr.Length % 255); + HashData(arr, initial); + Assert.False(ArrayExtensions.UnsafeEquals(arr, copy)); + + DeHashData(arr, initial); + Assert.True(ArrayExtensions.UnsafeEquals(arr, copy)); + } + + [Fact] + public void BytesEncodingTest() + { + // Arrange + var r = new Random((int)Environment.TickCount); + + for (int i = 1; i < 20; i ++) + { + // Act + var arr = new byte[i]; + var copy = new byte[i]; + r.NextBytes(arr); + Array.Copy(arr, copy, arr.Length); + + // Assert + + var initial = arr[0]; + HashData(arr, initial); + Assert.False(ArrayExtensions.UnsafeEquals(arr, copy)); + + DeHashData(arr, initial); + Assert.True(ArrayExtensions.UnsafeEquals(arr, copy)); + } + + for (int i = 1; i < 200000; i += 17) + { + // Act + var arr = new byte[i]; + var copy = new byte[i]; + r.NextBytes(arr); + Array.Copy(arr, copy, arr.Length); + + // Assert + + var initial = arr[0]; + HashData(arr, initial); + Assert.False(ArrayExtensions.UnsafeEquals(arr, copy)); + + DeHashData(arr, initial); + Assert.True(ArrayExtensions.UnsafeEquals(arr, copy)); + } + } + + } +} diff --git a/ZeroLevel/Services/Encryption/FastObfuscator.cs b/ZeroLevel/Services/Encryption/FastObfuscator.cs index 4f72368..389f87d 100644 --- a/ZeroLevel/Services/Encryption/FastObfuscator.cs +++ b/ZeroLevel/Services/Encryption/FastObfuscator.cs @@ -40,8 +40,19 @@ namespace ZeroLevel.Services.Encryption public void DeHashData(byte[] data) { - if (data.Length == 0) return; - for (var i = data.Length - 1; i > 0; i--) + int i; + for (i = data.Length - 1; i > 9; i -= 8) + { + data[i - 0] ^= data[i - 1]; + data[i - 1] ^= data[i - 2]; + data[i - 2] ^= data[i - 3]; + data[i - 3] ^= data[i - 4]; + data[i - 4] ^= data[i - 5]; + data[i - 5] ^= data[i - 6]; + data[i - 6] ^= data[i - 7]; + data[i - 7] ^= data[i - 8]; + } + for (; i >= 1; i--) { data[i] ^= data[i - 1]; } diff --git a/ZeroLevel/Services/HashFunctions/Murmur3.cs b/ZeroLevel/Services/HashFunctions/Murmur3.cs index 45dc758..68d25da 100644 --- a/ZeroLevel/Services/HashFunctions/Murmur3.cs +++ b/ZeroLevel/Services/HashFunctions/Murmur3.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; namespace ZeroLevel.Services.HashFunctions { @@ -149,9 +150,150 @@ namespace ZeroLevel.Services.HashFunctions return hash; } + public static ulong ComputeULongHash(byte[] bb, ulong seed = 0) + { + var h1 = seed; + ulong h2 = 0; + var length = 0UL; + int pos = 0; + ulong remaining = (ulong)bb.Length; + // read 128 bits, 16 bytes, 2 longs in eacy cycle + while (remaining >= READ_SIZE) + { + ulong k1 = bb.GetUInt64(pos); + pos += 8; + ulong k2 = bb.GetUInt64(pos); + pos += 8; + length += READ_SIZE; + remaining -= READ_SIZE; + + h1 ^= MixKey1(k1); + h1 = h1.RotateLeft(27); + h1 += h2; + h1 = h1 * 5 + 0x52dce729; + h2 ^= MixKey2(k2); + h2 = h2.RotateLeft(31); + h2 += h1; + h2 = h2 * 5 + 0x38495ab5; + } + + // if the input MOD 16 != 0 + if (remaining > 0) + { + ulong k1 = 0; + ulong k2 = 0; + length += remaining; + // little endian (x86) processing + switch (remaining) + { + case 15: + k2 ^= (ulong)bb[pos + 14] << 48; // fall through + goto case 14; + case 14: + k2 ^= (ulong)bb[pos + 13] << 40; // fall through + goto case 13; + case 13: + k2 ^= (ulong)bb[pos + 12] << 32; // fall through + goto case 12; + case 12: + k2 ^= (ulong)bb[pos + 11] << 24; // fall through + goto case 11; + case 11: + k2 ^= (ulong)bb[pos + 10] << 16; // fall through + goto case 10; + case 10: + k2 ^= (ulong)bb[pos + 9] << 8; // fall through + goto case 9; + case 9: + k2 ^= (ulong)bb[pos + 8]; // fall through + goto case 8; + case 8: + k1 ^= bb.GetUInt64(pos); + break; + case 7: + k1 ^= (ulong)bb[pos + 6] << 48; // fall through + goto case 6; + case 6: + k1 ^= (ulong)bb[pos + 5] << 40; // fall through + goto case 5; + case 5: + k1 ^= (ulong)bb[pos + 4] << 32; // fall through + goto case 4; + case 4: + k1 ^= (ulong)bb[pos + 3] << 24; // fall through + goto case 3; + case 3: + k1 ^= (ulong)bb[pos + 2] << 16; // fall through + goto case 2; + case 2: + k1 ^= (ulong)bb[pos + 1] << 8; // fall through + goto case 1; + case 1: + k1 ^= (ulong)bb[pos]; // fall through + break; + default: + throw new Exception("Something went wrong with remaining bytes calculation."); + } + h1 ^= MixKey1(k1); + h2 ^= MixKey2(k2); + } + + + h1 ^= length; + h2 ^= length; + + h1 += h2; + h2 += h1; + + h1 = Murmur3.MixFinal(h1); + h2 = Murmur3.MixFinal(h2); + + h1 += h2; + h2 += h1; + + return h2; + } + + /// + /// Hashes the into a MurmurHash3 as a . + /// + /// The span. + /// The seed for this algorithm. + /// The MurmurHash3 as a + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint ComputeUIntHash(ref ReadOnlySpan bytes, uint seed) + { + ref byte bp = ref MemoryMarshal.GetReference(bytes); + ref uint endPoint = ref Unsafe.Add(ref Unsafe.As(ref bp), bytes.Length >> 2); + if (bytes.Length >= 4) + { + do + { + seed = RotateLeft(seed ^ RotateLeft(Unsafe.ReadUnaligned(ref bp) * 3432918353U, 15) * 461845907U, 13) * 5 - 430675100; + bp = ref Unsafe.Add(ref bp, 4); + } while (Unsafe.IsAddressLessThan(ref Unsafe.As(ref bp), ref endPoint)); + } + var remainder = bytes.Length & 3; + if (remainder > 0) + { + uint num = 0; + if (remainder > 2) num ^= Unsafe.Add(ref endPoint, 2) << 16; + if (remainder > 1) num ^= Unsafe.Add(ref endPoint, 1) << 8; + num ^= endPoint; + + seed ^= RotateLeft(num * 3432918353U, 15) * 461845907U; + } + seed ^= (uint)bytes.Length; + seed = (uint)((seed ^ (seed >> 16)) * -2048144789); + seed = (uint)((seed ^ (seed >> 13)) * -1028477387); + return seed ^ seed >> 16; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static ulong RotateLeft(this ulong original, int bits) => (original << bits) | (original >> (64 - bits)); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static ulong RotateLeft(this ulong original, int bits) => - (original << bits) | (original >> (64 - bits)); + public static uint RotateLeft(this uint original, int bits) => (original << bits) | (original >> (32 - bits)); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ulong RotateRight(this ulong original, int bits) => diff --git a/ZeroLevel/Services/Mathemathics/Combinations.cs b/ZeroLevel/Services/Mathemathics/Combinations.cs new file mode 100644 index 0000000..e1fddb5 --- /dev/null +++ b/ZeroLevel/Services/Mathemathics/Combinations.cs @@ -0,0 +1,40 @@ +using System.Collections.Generic; + +namespace ZeroLevel.Services.Mathemathics +{ + public static class Combinations + { + private static IEnumerable GenerateIndiciesForUniqueSets(int m, int n) + { + int[] result = new int[m]; + Stack stack = new Stack(m); + stack.Push(0); + while (stack.Count > 0) + { + int index = stack.Count - 1; + int value = stack.Pop(); + while (value < n) + { + result[index++] = value++; + stack.Push(value); + if (index != m) continue; + yield return result; + break; + } + } + } + + public static IEnumerable GenerateUniqueSets(T[] original, int k) + { + T[] result = new T[k]; + foreach (var indices in GenerateIndiciesForUniqueSets(k, original.Length)) + { + for (int i = 0; i < k; i++) + { + result[i] = original[indices[i]]; + } + yield return result; + } + } + } +} diff --git a/ZeroLevel/ZeroLevel.csproj b/ZeroLevel/ZeroLevel.csproj index ec512c8..6d53858 100644 --- a/ZeroLevel/ZeroLevel.csproj +++ b/ZeroLevel/ZeroLevel.csproj @@ -8,7 +8,7 @@ True ZeroLevel $(AssemblyVersion) - 4.0.0.0 + 4.0.0.1 $(AssemblyVersion) latest Ogoun @@ -32,6 +32,10 @@ + + + + True