Created
November 13, 2018 06:49
-
-
Save mjs3339/5e5e921bfc906c5487b971ee8da0375e to your computer and use it in GitHub Desktop.
C# CryptoEntropy Source Class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class CryptoEntropy | |
{ | |
public readonly TinyHashSet<byte[]> _entropyTest; | |
public CryptoEntropy() | |
{ | |
EntropyRequested = 0; | |
_entropyTest = new TinyHashSet<byte[]>(new ArrayComparer()); | |
} | |
public byte[] Entropy => GetEntropy(); | |
public int EntropyRequested{get; private set;} | |
public bool UseTest { get; set; } | |
public double EntropyLevel { get; private set; } | |
[DllImport("kernel32.dll")] | |
private static extern int GetTickCount(); | |
[DllImport("kernel32.dll")] | |
internal static extern bool QueryPerformanceCounter(out long lpPerformanceCount); | |
[DllImport("kernel32.dll")] | |
internal static extern bool QueryPerformanceFrequency(out long lpFrequency); | |
private byte[] GetEntropy() | |
{ | |
var el = new List<string>(); | |
var hashBytes = new TinyHashSet<byte[]>(new ArrayComparer()); | |
var sw = new Stopwatch(); | |
sw.Start(); | |
hashBytes.Add(Process.GetCurrentProcess().Id.GetBytes()); | |
hashBytes.Add(Thread.CurrentThread.ManagedThreadId.GetBytes()); | |
hashBytes.Add(GetTickCount().GetBytes()); | |
hashBytes.Add(Process.GetProcesses().Length.GetBytes()); | |
QueryPerformanceFrequency(out var freq); | |
QueryPerformanceCounter(out var query); | |
hashBytes.Add(freq.GetBytes()); | |
hashBytes.Add(query.GetBytes()); | |
hashBytes.Add(DateTime.Now.Ticks.GetBytes()); | |
hashBytes.Add(Environment.UserName.GetBytes()); | |
hashBytes.Add(Environment.MachineName.GetBytes()); | |
hashBytes.Add(Environment.OSVersion.ToString().GetBytes()); | |
hashBytes.Add(Environment.ProcessorCount.GetBytes()); | |
hashBytes.Add(Environment.UserDomainName.GetBytes()); | |
hashBytes.Add(Environment.StackTrace.GetBytes()); | |
hashBytes.Add(Environment.GetLogicalDrives().GetBytes()); | |
hashBytes.Add(MemoryInfo.GetValues().GetBytesObject()); | |
hashBytes.Add(MemoryInfo.GetSystemPerformanceInformation().GetBytesObject()); | |
foreach(var p in Process.GetProcesses()) | |
{ | |
try | |
{ | |
hashBytes.Add(p.Id.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.Id.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.HandleCount.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.HandleCount.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.MainWindowTitle.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.MainWindowTitle.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.NonpagedSystemMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.NonpagedSystemMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PagedMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PagedMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PagedSystemMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PagedSystemMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PeakPagedMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PeakPagedMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PeakVirtualMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PeakVirtualMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PeakWorkingSet64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PeakWorkingSet64.GetBytes()"); | |
} | |
try | |
{ | |
hashBytes.Add(p.PrivateMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.PrivateMemorySize64.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.ProcessName.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.ProcessName.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.Threads.Count.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.Threads.Count.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.SessionId.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.SessionId.GetBytes())"); | |
} | |
for(var i = 0; i < p.Threads.Count; i++) | |
{ | |
try | |
{ | |
hashBytes.Add(p.Threads[i].CurrentPriority.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].CurrentPriority.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.Threads[i].Id.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].Id.GetBytes())"); | |
} | |
try | |
{ | |
hashBytes.Add(p.Threads[i].StartAddress.ToString().GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.Threads[i].StartAddress.ToString().GetBytes())"); | |
} | |
} | |
try | |
{ | |
hashBytes.Add(p.VirtualMemorySize64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.VirtualMemorySize64.GetBytes()))"); | |
} | |
try | |
{ | |
hashBytes.Add(p.WorkingSet64.GetBytes()); | |
} | |
catch(Exception ex) | |
{ | |
el.Add($"{ex.Message} hashBytes.Add(p.WorkingSet64.GetBytes()))"); | |
} | |
} | |
var csb = new CryptoJitterSeedBytes(); | |
hashBytes.Add(csb.SeedBuffer); | |
sw.Stop(); | |
hashBytes.Add(sw.Elapsed.Ticks.GetBytes()); | |
var ptr = 0; | |
var count = 0; | |
foreach(var hba in hashBytes) | |
count += hba.Length; | |
hashBytes.Add(count.GetBytes()); | |
count += hashBytes.Last().Length; | |
var rhb = new byte[count]; | |
foreach(var hba in hashBytes) | |
{ | |
Buffer.BlockCopy(hba, 0, rhb, ptr, hba.Length); | |
ptr += hba.Length; | |
} | |
EntropyLevel = GetEntropyLevel(rhb); | |
if(UseTest) | |
if(_entropyTest.Add(rhb)) | |
throw new Exception("Current Entropy Source is not unique."); | |
EntropyRequested++; | |
return rhb; | |
} | |
private static double GetEntropyLevel(byte[] ba) | |
{ | |
var map = new int[256]; | |
foreach (var i in ba) | |
map[i]++; | |
var lot = Math.Log(2); | |
return (from item in map where item > 0 select item / (double)ba.Length).Aggregate(0.0, (current, frequency) => current - frequency * (Math.Log(frequency) / lot)); | |
} | |
private static unsafe bool Compare(byte[] a1, byte[] a2) | |
{ | |
if(a1 == null && a2 == null) | |
return true; | |
if(a1 == null || a2 == null || a1.Length != a2.Length) | |
return false; | |
fixed(byte* p1 = a1, p2 = a2) | |
{ | |
var Len = a1.Length; | |
byte* x1 = p1, x2 = p2; | |
while(Len > 7) | |
{ | |
if(*(long*) x2 != *(long*) x1) | |
return false; | |
x1 += 8; | |
x2 += 8; | |
Len -= 8; | |
} | |
switch(Len % 8) | |
{ | |
case 0: | |
break; | |
case 7: | |
if(*(int*) x2 != *(int*) x1) | |
return false; | |
x1 += 4; | |
x2 += 4; | |
if(*(short*) x2 != *(short*) x1) | |
return false; | |
x1 += 2; | |
x2 += 2; | |
if(*x2 != *x1) | |
return false; | |
break; | |
case 6: | |
if(*(int*) x2 != *(int*) x1) | |
return false; | |
x1 += 4; | |
x2 += 4; | |
if(*(short*) x2 != *(short*) x1) | |
return false; | |
break; | |
case 5: | |
if(*(int*) x2 != *(int*) x1) | |
return false; | |
x1 += 4; | |
x2 += 4; | |
if(*x2 != *x1) | |
return false; | |
break; | |
case 4: | |
if(*(int*) x2 != *(int*) x1) | |
return false; | |
break; | |
case 3: | |
if(*(short*) x2 != *(short*) x1) | |
return false; | |
x1 += 2; | |
x2 += 2; | |
if(*x2 != *x1) | |
return false; | |
break; | |
case 2: | |
if(*(short*) x2 != *(short*) x1) | |
return false; | |
break; | |
case 1: | |
if(*x2 != *x1) | |
return false; | |
break; | |
} | |
return true; | |
} | |
} | |
private class ArrayComparer : IEqualityComparer<byte[]> | |
{ | |
private readonly FNV1a64 hash = new FNV1a64(); | |
public bool Equals(byte[] left, byte[] right) | |
{ | |
if(left == null || right == null) | |
return false; | |
return Compare(left.ToArray(), right.ToArray()); | |
} | |
public int GetHashCode(byte[] obj) | |
{ | |
return hash.ComputeHash(obj.ToArray()).ToInt(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment