Skip to content

Instantly share code, notes, and snippets.

@SidShetye
Last active August 29, 2015 14:04
Show Gist options
  • Save SidShetye/97631352f54a68184418 to your computer and use it in GitHub Desktop.
Save SidShetye/97631352f54a68184418 to your computer and use it in GitHub Desktop.
public class Entropy
{
private const long Prime = 179426549;
private const long Prime2 = 46633; // another prime
public static long GetEntropySeed()
{
return Ticks ^ ProcessInfoKey() ^ MemorySizeKey() ^ EnvironmentKey();
}
private static long Ticks
{
get
{
if (Environment.OSVersion.Platform == PlatformID.Win32Windows ||
Environment.OSVersion.Platform == PlatformID.Win32NT)
{
long x = 0;
NativeMethods.QueryPerformanceCounter(ref x);
return x;
}
return DateTime.Now.Ticks;
}
}
[SuppressUnmanagedCodeSecurity]
private static class NativeMethods
{
/// <summary>
/// High resolution timer (less than 1us)
/// </summary>
/// <param name="x"></param>
/// <returns></returns>
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
public static extern int QueryPerformanceCounter(ref long x);
}
private static string GetCommandOutput(string fn, string args)
{
var psi = new ProcessStartInfo(fn, args)
{
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
try
{
using (var process = Process.Start(psi))
{
if (process != null)
{
var o = process.StandardOutput.ReadToEnd();
var e = process.StandardError.ReadToEnd();
process.WaitForExit();
return o + e;
}
}
}
catch (Win32Exception) { }
catch (SystemException) { }
return String.Empty;
}
#region [Sources of entropy]
private static long ProcessInfoKey()
{
var commandHashes = new List<int>();
var processOffset = 0;
long data;
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
if (processOffset >= commandHashes.Count)
{
commandHashes.Clear();
var cmd = GetCommandOutput("/bin/ps", "-A v");
for (var i = 0; i < cmd.Length; i++)
commandHashes.Add(cmd.Substring(i, Math.Min(cmd.Length - i, 512)).GetHashCode());
}
processOffset = 0;
data = unchecked((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32));
while (processOffset < commandHashes.Count)
{
long ret = unchecked(commandHashes[processOffset++]);
ret ^= unchecked(data);
return ret;
}
return unchecked(data);
}
else
{
processOffset = 0;
var processes = Process.GetProcesses();
data = unchecked((int)((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32)));
while (processOffset < processes.Length)
{
long ret = 0;
if (ProcessInfoHash(processes[processOffset++], out ret))
{
ret ^= unchecked(data);
return ret;
}
}
return unchecked(data);
}
}
private static long MemorySizeKey()
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
var proc = Process.GetCurrentProcess();
try
{
long data = proc.PagedMemorySize64 & 0xFFFFFFFF;
data = unchecked(data << 32);
data |= proc.PrivateMemorySize64 & 0xFFFFFFFF;
return unchecked(data);
}
catch (PlatformNotSupportedException)
{
return unchecked((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32));
}
}
if (Environment.OSVersion.Platform == PlatformID.Unix)
{
var data = unchecked((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32));
if ((data & 0xFF) < 64)
{
using (var fs = new FileStream("/dev/urandom",
FileMode.Open))
{
var data2 = new byte[8];
fs.Read(data2, 0, data2.Length);
data ^= BitConverter.ToInt64(data2, 0);
}
}
return unchecked(data);
}
return unchecked((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32));
}
private static long EnvironmentKey()
{
long data = unchecked(((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32)));
try
{
var dict = Environment.GetEnvironmentVariables();
data = unchecked(data*Prime + dict.Count);
var keylist = new List<string>();
foreach (var o in dict.Keys)
{
keylist.Add((string) o);
}
for (var i = 0; i < keylist.Count; i++)
{
int shuffle = unchecked((int)((dict.Count == 0) ? 0 : (data & 0xFFFF) % dict.Count));
var index = (i + shuffle)%keylist.Count;
var key = keylist[index];
var k = key.GetHashCode();
var v = dict[key].GetHashCode();
unchecked
{
data = data * Prime + k;
data = data * Prime + v;
}
}
}
catch (SecurityException)
{
}
unchecked
{
data *= Prime;
data += (int)Environment.OSVersion.Platform;
data *= Prime;
data += Environment.StackTrace.GetHashCode();
}
return unchecked(data);
}
private static bool ProcessInfoHash(Process proc, out long retval)
{
long value = Prime2;
unchecked
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
long shuffle = 0; /* variable designed to shuffle the order
in which the process data is incorporated
into the hash code, to add unpredictability*/
try
{
value = value * Prime + proc.StartTime.Ticks.GetHashCode();
value = value * Prime + proc.PrivilegedProcessorTime.Ticks.GetHashCode();
value = value * Prime + proc.TotalProcessorTime.Ticks.GetHashCode();
shuffle = ((value ^ (Ticks & 0xFFFF)) % 6);
shuffle = Math.Abs(shuffle);
}
catch (NotSupportedException)
{
}
catch (InvalidOperationException)
{
}
catch (Win32Exception)
{
value = proc.PagedMemorySize64.GetHashCode();
shuffle = ((value ^ (Ticks & 0xFFFF)) % 6);
shuffle = Math.Abs(shuffle);
}
for (var i = 0; i < 6; i++)
{
var rv = (shuffle + i) % 6;
switch (rv)
{
case 0:
value *= Prime;
try
{
value += proc.Id;
}
catch (InvalidOperationException)
{
}
break;
case 1:
value = value * Prime + proc.PrivateMemorySize64.GetHashCode();
break;
case 2:
value = value * Prime + proc.WorkingSet64.GetHashCode();
break;
case 3:
value = value * Prime + proc.PagedMemorySize64.GetHashCode();
break;
case 4:
try
{
value = value * Prime + proc.Threads.Count;
if (proc.Threads.Count > 0)
{
var shuffle2 = Math.Abs(value % proc.Threads.Count);
for (var j = 0; j < proc.Threads.Count; j++)
{
var idx = (int) ((j + shuffle2) % proc.Threads.Count);
value = value * Prime + proc.Threads[idx].Id;
try
{
value = value * Prime +
proc.Threads[idx].TotalProcessorTime.GetHashCode();
value = value * Prime +
proc.Threads[idx].PrivilegedProcessorTime.GetHashCode();
}
catch (NotSupportedException)
{
}
catch (Win32Exception)
{
}
}
}
}
catch (SystemException)
{
}
break;
case 5:
value = value * Prime;
try
{
value += proc.ProcessName.GetHashCode();
}
catch (SystemException)
{
}
break;
}
}
}
else if (Environment.OSVersion.Platform == PlatformID.Win32Windows)
{
try
{
proc.StartInfo.UseShellExecute = false;
value = value * Prime;
try
{
value += proc.ProcessName.GetHashCode();
}
catch (SystemException)
{
}
value = value * Prime + (int)proc.HandleCount;
try
{
value = value * Prime + proc.Threads.Count;
if (proc.Threads.Count > 0)
{
var shuffle2 = Math.Abs(value % proc.Threads.Count);
for (var j = 0; j < proc.Threads.Count; j++)
{
var idx = (int) (j + shuffle2) % proc.Threads.Count;
value = value * Prime + proc.Threads[idx].Id;
}
}
}
catch (SystemException)
{
}
try
{
value = value * Prime + proc.Id;
}
catch (InvalidOperationException)
{
}
}
catch (PlatformNotSupportedException)
{
value = value * Prime;
value += unchecked((int)((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32)));
}
}
else
{
value = value * Prime;
value += unchecked((int)((Ticks & 0xFFFFFFFF) ^ (Ticks >> 32)));
}
}
retval = unchecked(value);
return true;
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment