Skip to content

Instantly share code, notes, and snippets.

@mjs3339
Created November 13, 2018 06:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjs3339/5e5e921bfc906c5487b971ee8da0375e to your computer and use it in GitHub Desktop.
Save mjs3339/5e5e921bfc906c5487b971ee8da0375e to your computer and use it in GitHub Desktop.
C# CryptoEntropy Source Class
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