RngJitterSource.cs

CPU RAM Jitter Driven RNG Data Source

using System;
using System.Diagnostics;
using System.Security.Cryptography;
using System.Threading;
public class RngJitterSource : RandomNumberGenerator
{
    /// <summary>
    ///     Recalculate buffer every 1000 milliseconds
    /// </summary>
    private const int ReSecureThresholdBf = 1000;
    private readonly SHA3ModInt _algorithm;
    private readonly object     _cacheLock = new object();
    private readonly int        _moveSize;
    /// <summary>
    ///     Just in case you need access to the underlying data
    /// </summary>
    public readonly JitterEx Jitter;
    private readonly Stopwatch tmr;
    private          byte[]    _cacheBuffer;
    private          int       _cacheSize;
    private volatile int       _ptr;
    private volatile int       BytesRemainingInCache;
    /// <summary>
    ///     If you want to use this as a flat memory pool
    ///     Use in conjunction with DataReady -- DataReady.WaitOne(); -- use data
    /// </summary>
    public volatile byte[] Cache;
    public  int    cacheFills;
    private Thread CacheThread;
    /// <summary>
    ///     See Cache above
    /// </summary>
    public AutoResetEvent DataReady = new AutoResetEvent(false);
    private bool Filled;
    public  int  ResecureCount;
    public RngJitterSource() : this(1024 * 1024, 1024, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize) : this(cacheSize, 1024, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4)
    {
    }
    public RngJitterSource(int cacheSize, int seedSize, int sha3Size, int sha3Rounds)
    {
        _cacheSize   = cacheSize;
        Jitter       = new JitterEx();
        _cacheBuffer = new byte[seedSize];
        Jitter.GetBytes(_cacheBuffer);
        Cache                 = new byte[_cacheSize];
        _ptr                  = 0;
        BytesRemainingInCache = 0;
        _algorithm            = new SHA3ModInt(sha3Size, sha3Rounds);
        _moveSize             = _algorithm.ComputeHash(2.GetBytes()).Length;
        Filled                = false;
        tmr                   = new Stopwatch();
        CacheThread           = new Thread(KeepFullCache) {Priority = ThreadPriority.Highest};
        CacheThread.Start();
    }
    public void Abort()
    {
        CacheThread.Abort();
    }
    protected override void Dispose(bool disposing)
    {
        _algorithm.Dispose();
    }
    public override void GetBytes(byte[] data)
    {
        if (data.Length > _cacheSize)
        {
            _cacheSize            = data.Length;
            Cache                 = new byte[_cacheSize];
            _ptr                  = 0;
            BytesRemainingInCache = 0;
            if (CacheThread.IsAlive)
                CacheThread.Abort();
            DataReady   = new AutoResetEvent(false);
            CacheThread = new Thread(KeepFullCache) {Priority = ThreadPriority.Highest};
            CacheThread.Start();
        }
        while (_ptr < data.Length)
            Thread.Sleep(10);
        DataReady.WaitOne();
        Buffer.BlockCopy(Cache, _ptr - data.Length, data, 0, data.Length);
        _ptr                  -= data.Length;
        BytesRemainingInCache -= data.Length;
    }
    private void KeepFullCache()
    {
        while (true)
            if (BytesRemainingInCache < _moveSize)
                lock (_cacheLock)
                {
                    var moveSize = _moveSize;
                    cacheFills++;
                    var bufferFills = 0;
                    tmr.Start();
                    while (true)
                    {
                        bufferFills++;
                        if (tmr.Elapsed.TotalMilliseconds >= ReSecureThresholdBf)
                        {
                            Jitter.GetBytes(_cacheBuffer);
                            tmr.Restart();
                            ResecureCount++;
                        }
                        var remainingBytesToMove = _cacheSize - _ptr;
                        if (remainingBytesToMove < moveSize)
                            moveSize = remainingBytesToMove;
                        if (remainingBytesToMove <= 0 || _ptr >= _cacheSize)
                            break;
                        _cacheBuffer = _algorithm.ComputeHash(_cacheBuffer);
                        Buffer.BlockCopy(_cacheBuffer, 0, Cache, _ptr, moveSize);
                        _ptr += moveSize;
                    }
                    tmr.Stop();
                    _ptr                  = _cacheSize;
                    BytesRemainingInCache = _cacheSize;
                    DataReady.Set();
                }
            else
                DataReady.Set();
    }
}

EntropyGeneric.cs

Detect Entropy Levels from Primitive Data Arrays

using System;
using System.Collections.Generic;
public class EntropyGeneric<T>
{
    private const    double             NaturalLogOfTwo = 0.69314718055994530941723212145818;
    private readonly Dictionary<T, int> _hist           = new Dictionary<T, int>();
    private          bool               _mapStatus;
    public EntropyGeneric()
    {
        _hist.Clear();
        _mapStatus = false;
    }
    public (double entropy, int perfect) Entropy(T[] s)
    {
        if (_mapStatus)
        {
            _hist.Clear();
            _mapStatus = false;
        }
        foreach (var c in s)
            if (!_hist.ContainsKey(c))
                _hist.Add(c, 1);
            else
                _hist[c] += 1;
        _mapStatus = true;
        var e = 0.0;
        foreach (var v in _hist.Values)
        {
            if (v <= 0)
                continue;
            var r = v             / (double) s.Length;
            e -= r * (Math.Log(r) / NaturalLogOfTwo);
        }
        return (e, GetSize());
    }
    private byte[] ConvertTypeByteArray(T[] ia)
    {
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean:
                break;
            case TypeCode.Char:
                break;
            case TypeCode.SByte:
                break;
            case TypeCode.Byte:
                break;
            case TypeCode.Int16:
                break;
            case TypeCode.UInt16:
                break;
            case TypeCode.Int32:
                break;
            case TypeCode.UInt32:
                break;
            case TypeCode.Single:
                break;
            case TypeCode.String:
                break;
            case TypeCode.Decimal:
                break;
            case TypeCode.Int64:
                break;
            case TypeCode.UInt64:
                break;
            case TypeCode.Double:
                break;
            case TypeCode.DateTime:
                break;
            default:
                throw new ArgumentException("Type is not a valid primitive.");
        }
        return ia.GetBytesObject();
    }
    private int GetSize()
    {
        var size = 0;
        switch (Type.GetTypeCode(typeof(T)))
        {
            case TypeCode.Boolean:
                size = 8;
                break;
            case TypeCode.Char:
                size = 16;
                break;
            case TypeCode.SByte:
                size = 8;
                break;
            case TypeCode.Byte:
                size = 8;
                break;
            case TypeCode.Int16:
                size = 16;
                break;
            case TypeCode.UInt16:
                size = 16;
                break;
            case TypeCode.Int32:
                size = 32;
                break;
            case TypeCode.UInt32:
                size = 32;
                break;
            case TypeCode.Single:
                size = 32;
                break;
            case TypeCode.String:
                size = 32;
                break;
            case TypeCode.Decimal:
                size = 96;
                break;
            case TypeCode.Int64:
                size = 64;
                break;
            case TypeCode.UInt64:
                size = 64;
                break;
            case TypeCode.Double:
                size = 64;
                break;
            case TypeCode.DateTime:
                size = 64;
                break;
            default:
                throw new ArgumentException("Type is not a valid primitive.");
        }
        return size;
    }
}

EntropySource.cs

Using PC Data Creates a Strong Entropy Source

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
public class EntropySource
{
    private const int Sha3BitSize           = 256;
    private const int Sha3BitBufferMoveSize = Sha3BitSize >> 3;
    private const int CpuDataLength         = 256;
    private const int JitterDataSize        = 256;
    [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);
    public static byte[] GetBuffer(int bufferSize)
    {
        var rhb = new byte[0];
        var rho = new byte[bufferSize];
        var EntropyThread = new Thread(() =>
        {
            var el        = new List<string>();
            var hashBytes = new HashSet<byte[]>(new ArrayComparer());
            var sw        = new Stopwatch();
            sw.Start();
            AddLocalUserData(hashBytes);
            AddProcessInformation(hashBytes, el);
            AddJitterInformation(hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfOS_Processor",              hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfOS_System",                 hashBytes);
            GetWmiInfor("Win32_PerfRawData_Counters_ProcessorInformation", hashBytes);
            GetWmiInfor("Win32_PerfRawData_Counters_Synchronization",      hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfDisk_LogicalDisk",          hashBytes);
            GetWmiInfor("Win32_PerfRawData_PerfDisk_PhysicalDisk",         hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Cache",            hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Memory",           hashBytes);
            GetWmiInfor("Win32_PerfFormattedData_PerfOS_Objects",          hashBytes);
            CpuInfo(hashBytes);
            sw.Stop();
            hashBytes.Add(sw.Elapsed.Ticks.GetBytes());
            rhb = HashBytesToArray(hashBytes);
            AddHistogramInforamation(rhb, hashBytes);
            rhb = HashBytesToArray(hashBytes);
            hashBytes.Clear();
            var div = bufferSize / Sha3BitBufferMoveSize;
            if (div * Sha3BitBufferMoveSize < bufferSize)
                div++;
            var segSize = rhb.Length / div;
            var aseg    = new byte[segSize];
            for (var i = 0; i < div; ++i)
            {
                Buffer.BlockCopy(rhb,                                            i * segSize, aseg, 0,                         segSize);
                Buffer.BlockCopy(new SHA3Managed(Sha3BitSize).ComputeHash(aseg), 0,           rho,  i * Sha3BitBufferMoveSize, Sha3BitBufferMoveSize);
            }
        }) {Priority = ThreadPriority.Highest};
        EntropyThread.Start();
        EntropyThread.Join();
        return rho;
    }
    private static void GetWmiInfor(string key, HashSet<byte[]> hashBytes)
    {
        var wmi = new WMIServices();
        wmi.GetProperties(key);
        foreach (var v in wmi.EntriesList)
        foreach (var p in v.Value)
            hashBytes.Add(p.GetBytesObject());
    }
    private static void CpuInfo(HashSet<byte[]> hashBytes)
    {
        var lhashBytes = new HashSet<byte[]>();
        var dump       = CpuTotalPc.CPULoad;
        do
        {
            var l = (byte) CpuTotalPc.CPULoad;
            if (l != 0)
                lhashBytes.Add(new[] {l});
            Thread.Sleep(1);
        } while (lhashBytes.Count < CpuDataLength);
        foreach (var b in lhashBytes)
            hashBytes.Add(b);
    }
    private static void AddHistogramInforamation(byte[] rhb, HashSet<byte[]> hashBytes)
    {
        var FFTArray = Histogram(rhb);
        for (var i = 0; i < FFTArray.Length; ++i)
            hashBytes.Add(FFTArray[i].GetBytes());
    }
    private static void AddJitterInformation(HashSet<byte[]> hashBytes)
    {
        hashBytes.Add(new JitterEx(JitterDataSize).GetBuffer());
    }
    private static void AddProcessInformation(HashSet<byte[]> hashBytes, List<string> el)
    {
        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.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()))");
            }
        }
    }
    private static void AddLocalUserData(HashSet<byte[]> hashBytes)
    {
        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);
        hashBytes.Add(freq.GetBytes());
        for (var i = 0; i < 128; i++)
        {
            QueryPerformanceCounter(out var query);
            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().GetBytesObjectSerial());
        hashBytes.Add(MemoryInfo.GetSystemPerformanceInformation().GetBytesObjectSerial());
    }
    private static byte[] HashBytesToArray(HashSet<byte[]> hashBytes)
    {
        byte[] rhb;
        var    ptr   = 0;
        var    count = 0;
        var    arr   = hashBytes.ToArray();
        foreach (var hba in arr)
            count += hba.Length;
        hashBytes.Add(count.GetBytes());
        arr   =  hashBytes.ToArray();
        count += arr.Last().Length;
        rhb   =  new byte[count];
        foreach (var hba in arr)
        {
            Buffer.BlockCopy(hba, 0, rhb, ptr, hba.Length);
            ptr += hba.Length;
        }
        return rhb;
    }
    private static int[] Histogram(IEnumerable<byte> ba)
    {
        var map = new int[256];
        foreach (var i in ba)
            map[i]++;
        return map;
    }
}