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();
}
}
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(); } }
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();
    }
}

JitterCacheRng.cs

using System;
using System.Security.Cryptography;
using System.Threading;
[Serializable]
public class JitterCacheRng : RandomNumberGenerator
{
private const int ReSecureThreshold = 10;
private readonly SHA3ModInt _algorithm;
private readonly JitterEx _jit;
private readonly int _moveSize;
private int _availableCacheBytes;
private byte[] _cache;
private byte[] _cacheBuffer;
private int _cacheSize;
private int _ptr;
public int cacheFills;
public JitterCacheRng() : this(1048576, 256, 256, 4)
{
}
public JitterCacheRng(int cacheSize) : this(cacheSize, 256, 256, 4)
{
}
public JitterCacheRng(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4)
{
}
public JitterCacheRng(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4)
{
}
public JitterCacheRng(int cacheSize, int seedSize, int sha3Size, int sha3Rounds)
{
if (cacheSize == 0)
throw new ArgumentException("Cache Size cannot be zero");
if (seedSize < 256)
throw new ArgumentException("The seed size should be 256 or more bytes.");
if (sha3Size < 64 && sha3Size % 64 != 0)
throw new ArgumentException("The bitWidth of the SHA3 hash algorithm need to be at least 64 bits and a multiple of 64.");
if (sha3Rounds < 4)
throw new ArgumentException("Sha3 rounds of less than 4 might produce some short run repetitive sequences.");
_cacheSize = cacheSize;
_jit = new JitterEx(seedSize);
_cacheBuffer = _jit.GetBuffer();
_cache = new byte[_cacheSize];
_algorithm = new SHA3ModInt(sha3Size, sha3Rounds);
_moveSize = _algorithm.ComputeHash(2.GetBytes()).Length;
FillCache();
}
public bool Protect
{
get;
set;
}
protected override void Dispose(bool disposing)
{
_cache.Fill(0);
_availableCacheBytes = 0;
_algorithm.Dispose();
}
public override void GetBytes(byte[] data)
{
if (data.Length > _cacheSize)
{
_cacheSize = data.Length;
_cache = new byte[_cacheSize];
FillCache();
}
if (_availableCacheBytes == 0 || _availableCacheBytes < data.Length)
{
if (_cacheSize < data.Length)
{
_cacheSize = data.Length;
_cache = new byte[_cacheSize];
}
FillCache();
}
if (_ptr + data.Length > _cacheSize)
FillCache();
if (Protect)
ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);
Buffer.BlockCopy(_cache, _ptr, data, 0, data.Length);
if (Protect)
ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);
_ptr += data.Length;
_availableCacheBytes -= data.Length;
}
private void FillCache()
{
var btrd = new Thread(() =>
{
_availableCacheBytes = 0;
_ptr = 0;
var p = 0;
var moveSize = _moveSize;
cacheFills++;
if (cacheFills % ReSecureThreshold == 0)
_cacheBuffer = _jit.GetBuffer();
if (Protect)
ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);
while (true)
{
var remainingBytesToMove = _cacheSize - _availableCacheBytes;
if (remainingBytesToMove < moveSize)
moveSize = remainingBytesToMove;
if (remainingBytesToMove <= 0)
break;
_cacheBuffer = _algorithm.ComputeHash(_cacheBuffer);
Buffer.BlockCopy(_cacheBuffer, 0, _cache, p, moveSize);
p += moveSize;
_availableCacheBytes += moveSize;
}
if (Protect)
ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);
}) {Priority = ThreadPriority.Highest};
btrd.Start();
btrd.Join();
}
}
using System; using System.Security.Cryptography; using System.Threading; [Serializable] public class JitterCacheRng : RandomNumberGenerator { private const int ReSecureThreshold = 10; private readonly SHA3ModInt _algorithm; private readonly JitterEx _jit; private readonly int _moveSize; private int _availableCacheBytes; private byte[] _cache; private byte[] _cacheBuffer; private int _cacheSize; private int _ptr; public int cacheFills; public JitterCacheRng() : this(1048576, 256, 256, 4) { } public JitterCacheRng(int cacheSize) : this(cacheSize, 256, 256, 4) { } public JitterCacheRng(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4) { } public JitterCacheRng(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4) { } public JitterCacheRng(int cacheSize, int seedSize, int sha3Size, int sha3Rounds) { if (cacheSize == 0) throw new ArgumentException("Cache Size cannot be zero"); if (seedSize < 256) throw new ArgumentException("The seed size should be 256 or more bytes."); if (sha3Size < 64 && sha3Size % 64 != 0) throw new ArgumentException("The bitWidth of the SHA3 hash algorithm need to be at least 64 bits and a multiple of 64."); if (sha3Rounds < 4) throw new ArgumentException("Sha3 rounds of less than 4 might produce some short run repetitive sequences."); _cacheSize = cacheSize; _jit = new JitterEx(seedSize); _cacheBuffer = _jit.GetBuffer(); _cache = new byte[_cacheSize]; _algorithm = new SHA3ModInt(sha3Size, sha3Rounds); _moveSize = _algorithm.ComputeHash(2.GetBytes()).Length; FillCache(); } public bool Protect { get; set; } protected override void Dispose(bool disposing) { _cache.Fill(0); _availableCacheBytes = 0; _algorithm.Dispose(); } public override void GetBytes(byte[] data) { if (data.Length > _cacheSize) { _cacheSize = data.Length; _cache = new byte[_cacheSize]; FillCache(); } if (_availableCacheBytes == 0 || _availableCacheBytes < data.Length) { if (_cacheSize < data.Length) { _cacheSize = data.Length; _cache = new byte[_cacheSize]; } FillCache(); } if (_ptr + data.Length > _cacheSize) FillCache(); if (Protect) ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon); Buffer.BlockCopy(_cache, _ptr, data, 0, data.Length); if (Protect) ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon); _ptr += data.Length; _availableCacheBytes -= data.Length; } private void FillCache() { var btrd = new Thread(() => { _availableCacheBytes = 0; _ptr = 0; var p = 0; var moveSize = _moveSize; cacheFills++; if (cacheFills % ReSecureThreshold == 0) _cacheBuffer = _jit.GetBuffer(); if (Protect) ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon); while (true) { var remainingBytesToMove = _cacheSize - _availableCacheBytes; if (remainingBytesToMove < moveSize) moveSize = remainingBytesToMove; if (remainingBytesToMove <= 0) break; _cacheBuffer = _algorithm.ComputeHash(_cacheBuffer); Buffer.BlockCopy(_cacheBuffer, 0, _cache, p, moveSize); p += moveSize; _availableCacheBytes += moveSize; } if (Protect) ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon); }) {Priority = ThreadPriority.Highest}; btrd.Start(); btrd.Join(); } }
using System;
using System.Security.Cryptography;
using System.Threading;
[Serializable]
public class JitterCacheRng : RandomNumberGenerator
{
    private const    int        ReSecureThreshold = 10;
    private readonly SHA3ModInt _algorithm;
    private readonly JitterEx   _jit;
    private readonly int        _moveSize;
    private          int        _availableCacheBytes;
    private          byte[]     _cache;
    private          byte[]     _cacheBuffer;
    private          int        _cacheSize;
    private          int        _ptr;
    public           int        cacheFills;
    public JitterCacheRng() : this(1048576, 256, 256, 4)
    {
    }
    public JitterCacheRng(int cacheSize) : this(cacheSize, 256, 256, 4)
    {
    }
    public JitterCacheRng(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4)
    {
    }
    public JitterCacheRng(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4)
    {
    }
    public JitterCacheRng(int cacheSize, int seedSize, int sha3Size, int sha3Rounds)
    {
        if (cacheSize == 0)
            throw new ArgumentException("Cache Size cannot be zero");
        if (seedSize < 256)
            throw new ArgumentException("The seed size should be 256 or more bytes.");
        if (sha3Size < 64 && sha3Size % 64 != 0)
            throw new ArgumentException("The bitWidth of the SHA3 hash algorithm need to be at least 64 bits and a multiple of 64.");
        if (sha3Rounds < 4)
            throw new ArgumentException("Sha3 rounds of less than 4 might produce some short run repetitive sequences.");
        _cacheSize   = cacheSize;
        _jit         = new JitterEx(seedSize);
        _cacheBuffer = _jit.GetBuffer();
        _cache       = new byte[_cacheSize];
        _algorithm   = new SHA3ModInt(sha3Size, sha3Rounds);
        _moveSize    = _algorithm.ComputeHash(2.GetBytes()).Length;
        FillCache();
    }
    public bool Protect
    {
        get;
        set;
    }
    protected override void Dispose(bool disposing)
    {
        _cache.Fill(0);
        _availableCacheBytes = 0;
        _algorithm.Dispose();
    }
    public override void GetBytes(byte[] data)
    {
        if (data.Length > _cacheSize)
        {
            _cacheSize = data.Length;
            _cache     = new byte[_cacheSize];
            FillCache();
        }
        if (_availableCacheBytes == 0 || _availableCacheBytes < data.Length)
        {
            if (_cacheSize < data.Length)
            {
                _cacheSize = data.Length;
                _cache     = new byte[_cacheSize];
            }
            FillCache();
        }
        if (_ptr + data.Length > _cacheSize)
            FillCache();
        if (Protect)
            ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);
        Buffer.BlockCopy(_cache, _ptr, data, 0, data.Length);
        if (Protect)
            ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);
        _ptr                 += data.Length;
        _availableCacheBytes -= data.Length;
    }
    private void FillCache()
    {
        var btrd = new Thread(() =>
        {
            _availableCacheBytes = 0;
            _ptr                 = 0;
            var p        = 0;
            var moveSize = _moveSize;
            cacheFills++;
            if (cacheFills % ReSecureThreshold == 0)
                _cacheBuffer = _jit.GetBuffer();
            if (Protect)
                ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);
            while (true)
            {
                var remainingBytesToMove = _cacheSize - _availableCacheBytes;
                if (remainingBytesToMove < moveSize)
                    moveSize = remainingBytesToMove;
                if (remainingBytesToMove <= 0)
                    break;
                _cacheBuffer = _algorithm.ComputeHash(_cacheBuffer);
                Buffer.BlockCopy(_cacheBuffer, 0, _cache, p, moveSize);
                p                    += moveSize;
                _availableCacheBytes += moveSize;
            }
            if (Protect)
                ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);
        }) {Priority = ThreadPriority.Highest};
        btrd.Start();
        btrd.Join();
    }
}

JitterEx.cs

//#define TEST
using System;
using System.Diagnostics;
using System.Management;
using System.Runtime.CompilerServices;
using System.Threading;
[Serializable]
public class JitterEx
{
private const int DesaturationLoopLimit = 500;
private const int UpperCpuLoadLimit = 90;
private const int LowerCpuLoadLimit = 10;
private static bool _scaleSet;
private readonly int _bufferSize;
private readonly object _lock = new object();
private readonly Random _prng;
private byte[] _rngCache;
private int _tscLoopLimitCpu = 10;
private int _tscSampleSizeRam = 18;
public JitterEx(int buffersize, bool randomize = false)
{
_bufferSize = buffersize;
_rngCache = new byte[_bufferSize];
_prng = new Random();
Randomize = randomize;
SetScale();
}
public bool Randomize
{
get;
set;
}
#if TEST
public void TestListF()
{
var rlst = new List<List<(byte[], int)>>();
for (var i = 0; i < TestList.Count; i++)
{
var f = TestList[i];
for (var j = i + 1; j < TestList.Count; j++)
{
var s = TestList[j];
rlst.Add(new BMPartialPatternSearch(3).SearchPartialAll(f, s));
}
}
}
#endif
[MethodImpl(MethodImplOptions.NoOptimization)]
private float GetCpuSpeed()
{
void Loop()
{
var i = 0;
while (true)
i = i + 1 - 1;
}
var cpuCounter = new PerformanceCounter("Processor Information", "% Processor Performance", "_Total");
var cpuValue = cpuCounter.NextValue();
var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
var Speed = 0f;
lock (_lock)
{
loop.Start();
Thread.Sleep(60);
cpuValue = cpuCounter.NextValue();
loop.Abort();
}
foreach (ManagementObject obj in new ManagementObjectSearcher("SELECT *, Name FROM Win32_Processor").Get())
{
var v = Convert.ToSingle(obj["MaxClockSpeed"]);
Speed = v / 1000 * cpuValue / 100;
}
return Speed;
}
/// <summary>
/// This is a fairly arbitrary value which is based on the CPU speed. 4.7 is the speed on which the tests are based.
/// </summary>
private void SetScale()
{
if (_scaleSet)
return;
_scaleSet = true;
const float baseFreq = 4.7f;
var thisFreq = GetCpuSpeed();
var rat = baseFreq / thisFreq;
_tscLoopLimitCpu = (int) Math.Ceiling(_tscLoopLimitCpu * rat);
_tscSampleSizeRam = (int) Math.Ceiling(_tscSampleSizeRam * rat);
}
private void LoadBlock()
{
var DesaturationLoops = 0;
var dump = CpuTotalPc.CPULoad;
do
{
Thread.Sleep(0);
DesaturationLoops++;
} while (DesaturationLoops < DesaturationLoopLimit && ((int) CpuTotalPc.CPULoad > UpperCpuLoadLimit || (int) CpuTotalPc.CPULoad < LowerCpuLoadLimit));
}
[MethodImpl(MethodImplOptions.NoInlining)]
private byte[] GetBufferCpu()
{
void Loop()
{
var x = 0;
for (var i = 0; i < _tscLoopLimitCpu; i++)
x = x + 1 - 1;
}
var jitterBuffer = new byte[_bufferSize];
var ptr = 0;
LoadBlock();
lock (_lock)
{
var start = Rdtsc.TimestampP();
do
{
var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
loop.Start();
loop.Join();
var stop = Rdtsc.TimestampP();
Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
start = stop;
ptr += 4;
} while (ptr < _bufferSize);
return jitterBuffer;
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
private unsafe byte[] GetBufferRam()
{
void Loop()
{
byte tempByte;
fixed (byte* p1 = _rngCache)
{
var x1 = p1;
for (var j = 0; j < _tscSampleSizeRam; ++j, ++x1)
tempByte = *x1;
}
}
LoadBlock();
var jitterBuffer = new byte[_bufferSize];
lock (_lock)
{
if (_rngCache.Length != _bufferSize)
_rngCache = new byte[_bufferSize];
_prng.NextBytes(_rngCache);
var ptr = 0;
var start = Rdtsc.TimestampP();
while (true)
{
do
{
var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
loop.Start();
loop.Join();
var stop = Rdtsc.TimestampP();
Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
start = stop;
ptr += 4;
if (ptr < _bufferSize)
{
if (_rngCache.Length != _bufferSize)
_rngCache = new byte[_bufferSize];
_prng.NextBytes(_rngCache);
}
} while (ptr < _bufferSize);
return jitterBuffer;
}
}
}
public byte[] GetBuffer()
{
var firstBuffer = GetBufferCpu();
#if TEST
///Weighting add 15%, perfection is not what we are looking for here.
var lim = _bufferSize <= 256 ? _bufferSize / 256.0 * 85.0 : 6.8;
if (ent.Entropy(firstBuffer) < lim)
throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
var secondBuffer = GetBufferRam();
#if TEST
if (ent.Entropy(secondBuffer) < lim)
throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
var finalBuffer = new byte[_bufferSize];
for (var j = 0; j < _bufferSize; ++j)
finalBuffer[j] = (byte) (firstBuffer[j] ^ secondBuffer[j]);
#if TEST
if (ent.Entropy(finalBuffer) < lim)
throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
if (Randomize)
{
var ula = CreateNoiseArrays(finalBuffer);
var rBlock = new byte[ula.Length * 8];
Buffer.BlockCopy(ula, 0, rBlock, 0, ula.Length * 8);
#if TEST
if (_bufferSize >= 256)
{
var loop = new Thread(() =>
{
if (!rBlock.ChiSquaredTest().isRandom)
MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);
}) {Priority = ThreadPriority.Highest};
loop.Start();
}
TestList.Add(rBlock);
#endif
return rBlock;
}
#if TEST
if (_bufferSize >= 256)
{
var loop = new Thread(() =>
{
if (!finalBuffer.ChiSquaredTest().isRandom)
MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);
}) {Priority = ThreadPriority.Highest};
loop.Start();
}
TestList.Add(finalBuffer);
#endif
return finalBuffer;
}
private ulong[] ByteArrayToULongArray(byte[] ba, int finalSize)
{
var minSize = ba.Length / 8;
if (finalSize < minSize)
finalSize = minSize;
ba = PadULong(ba);
var result = new ulong[finalSize];
for (var i = 0; i < ba.Length; i += 8)
Buffer.BlockCopy(ba, i, result, i, 8);
return result;
}
private static byte[] PadULong(byte[] ba)
{
var s = ba.Length % 8;
switch (s)
{
case 0:
break;
case 1:
Array.Resize(ref ba, ba.Length + 7);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
ba[ba.Length - 3] = 0x80;
ba[ba.Length - 4] = 0x80;
ba[ba.Length - 5] = 0x80;
ba[ba.Length - 6] = 0x80;
ba[ba.Length - 7] = 0x80;
break;
case 2:
Array.Resize(ref ba, ba.Length + 6);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
ba[ba.Length - 3] = 0x80;
ba[ba.Length - 4] = 0x80;
ba[ba.Length - 5] = 0x80;
ba[ba.Length - 6] = 0x80;
break;
case 3:
Array.Resize(ref ba, ba.Length + 5);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
ba[ba.Length - 3] = 0x80;
ba[ba.Length - 4] = 0x80;
ba[ba.Length - 5] = 0x80;
break;
case 4:
Array.Resize(ref ba, ba.Length + 4);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
ba[ba.Length - 3] = 0x80;
ba[ba.Length - 4] = 0x80;
break;
case 5:
Array.Resize(ref ba, ba.Length + 3);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
ba[ba.Length - 3] = 0x80;
break;
case 6:
Array.Resize(ref ba, ba.Length + 2);
ba[ba.Length - 1] = 0x80;
ba[ba.Length - 2] = 0x80;
break;
case 7:
Array.Resize(ref ba, ba.Length + 1);
ba[ba.Length - 1] = 0x80;
break;
}
return ba;
}
private static void Extrude(ulong[] x)
{
var size = x.Length;
for (var i = 0; i < size; i++)
{
ulong n = 0;
var j = 0;
while (j < size)
{
n ^= x[j];
++j;
}
x[i] = (n << 1) | (n >> 56);
}
}
private ulong[] CreateNoiseArrays(byte[] ba)
{
var ula = ByteArrayToULongArray(ba, ba.Length / 8);
Extrude(ula);
return ula;
}
internal class EntropyI
{
private const double NaturalLogOfTwo = 0.69314718055994530941723212145818; //Math.Log(2);
/// <summary>
/// Get the Entropy from 1 to 100% 1 being very ordered data,
/// 100% being very disordered data.
/// </summary>
public double Entropy(byte[] a)
{
var h = new int[256];
var l = a.Length;
for (var i = 0; i < l; ++i)
h[a[i]]++;
var e = 0.0;
for (var i = 0; i < 256; ++i)
{
var v = h[i];
if (v <= 0)
continue;
var r = v / (double) l;
e -= r * (Math.Log(r) / NaturalLogOfTwo);
}
return e / 8.0 * 100.0;
}
}
#if TEST
private EntropyI ent = new EntropyI();
private List<byte[]> TestList = new List<byte[]>();
#endif
}
//#define TEST using System; using System.Diagnostics; using System.Management; using System.Runtime.CompilerServices; using System.Threading; [Serializable] public class JitterEx { private const int DesaturationLoopLimit = 500; private const int UpperCpuLoadLimit = 90; private const int LowerCpuLoadLimit = 10; private static bool _scaleSet; private readonly int _bufferSize; private readonly object _lock = new object(); private readonly Random _prng; private byte[] _rngCache; private int _tscLoopLimitCpu = 10; private int _tscSampleSizeRam = 18; public JitterEx(int buffersize, bool randomize = false) { _bufferSize = buffersize; _rngCache = new byte[_bufferSize]; _prng = new Random(); Randomize = randomize; SetScale(); } public bool Randomize { get; set; } #if TEST public void TestListF() { var rlst = new List<List<(byte[], int)>>(); for (var i = 0; i < TestList.Count; i++) { var f = TestList[i]; for (var j = i + 1; j < TestList.Count; j++) { var s = TestList[j]; rlst.Add(new BMPartialPatternSearch(3).SearchPartialAll(f, s)); } } } #endif [MethodImpl(MethodImplOptions.NoOptimization)] private float GetCpuSpeed() { void Loop() { var i = 0; while (true) i = i + 1 - 1; } var cpuCounter = new PerformanceCounter("Processor Information", "% Processor Performance", "_Total"); var cpuValue = cpuCounter.NextValue(); var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest}; var Speed = 0f; lock (_lock) { loop.Start(); Thread.Sleep(60); cpuValue = cpuCounter.NextValue(); loop.Abort(); } foreach (ManagementObject obj in new ManagementObjectSearcher("SELECT *, Name FROM Win32_Processor").Get()) { var v = Convert.ToSingle(obj["MaxClockSpeed"]); Speed = v / 1000 * cpuValue / 100; } return Speed; } /// <summary> /// This is a fairly arbitrary value which is based on the CPU speed. 4.7 is the speed on which the tests are based. /// </summary> private void SetScale() { if (_scaleSet) return; _scaleSet = true; const float baseFreq = 4.7f; var thisFreq = GetCpuSpeed(); var rat = baseFreq / thisFreq; _tscLoopLimitCpu = (int) Math.Ceiling(_tscLoopLimitCpu * rat); _tscSampleSizeRam = (int) Math.Ceiling(_tscSampleSizeRam * rat); } private void LoadBlock() { var DesaturationLoops = 0; var dump = CpuTotalPc.CPULoad; do { Thread.Sleep(0); DesaturationLoops++; } while (DesaturationLoops < DesaturationLoopLimit && ((int) CpuTotalPc.CPULoad > UpperCpuLoadLimit || (int) CpuTotalPc.CPULoad < LowerCpuLoadLimit)); } [MethodImpl(MethodImplOptions.NoInlining)] private byte[] GetBufferCpu() { void Loop() { var x = 0; for (var i = 0; i < _tscLoopLimitCpu; i++) x = x + 1 - 1; } var jitterBuffer = new byte[_bufferSize]; var ptr = 0; LoadBlock(); lock (_lock) { var start = Rdtsc.TimestampP(); do { var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest}; loop.Start(); loop.Join(); var stop = Rdtsc.TimestampP(); Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4); start = stop; ptr += 4; } while (ptr < _bufferSize); return jitterBuffer; } } [MethodImpl(MethodImplOptions.NoInlining)] private unsafe byte[] GetBufferRam() { void Loop() { byte tempByte; fixed (byte* p1 = _rngCache) { var x1 = p1; for (var j = 0; j < _tscSampleSizeRam; ++j, ++x1) tempByte = *x1; } } LoadBlock(); var jitterBuffer = new byte[_bufferSize]; lock (_lock) { if (_rngCache.Length != _bufferSize) _rngCache = new byte[_bufferSize]; _prng.NextBytes(_rngCache); var ptr = 0; var start = Rdtsc.TimestampP(); while (true) { do { var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest}; loop.Start(); loop.Join(); var stop = Rdtsc.TimestampP(); Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4); start = stop; ptr += 4; if (ptr < _bufferSize) { if (_rngCache.Length != _bufferSize) _rngCache = new byte[_bufferSize]; _prng.NextBytes(_rngCache); } } while (ptr < _bufferSize); return jitterBuffer; } } } public byte[] GetBuffer() { var firstBuffer = GetBufferCpu(); #if TEST ///Weighting add 15%, perfection is not what we are looking for here. var lim = _bufferSize <= 256 ? _bufferSize / 256.0 * 85.0 : 6.8; if (ent.Entropy(firstBuffer) < lim) throw new Exception("Error CPU Jitter Buffer Contains only zeros."); #endif var secondBuffer = GetBufferRam(); #if TEST if (ent.Entropy(secondBuffer) < lim) throw new Exception("Error CPU Jitter Buffer Contains only zeros."); #endif var finalBuffer = new byte[_bufferSize]; for (var j = 0; j < _bufferSize; ++j) finalBuffer[j] = (byte) (firstBuffer[j] ^ secondBuffer[j]); #if TEST if (ent.Entropy(finalBuffer) < lim) throw new Exception("Error CPU Jitter Buffer Contains only zeros."); #endif if (Randomize) { var ula = CreateNoiseArrays(finalBuffer); var rBlock = new byte[ula.Length * 8]; Buffer.BlockCopy(ula, 0, rBlock, 0, ula.Length * 8); #if TEST if (_bufferSize >= 256) { var loop = new Thread(() => { if (!rBlock.ChiSquaredTest().isRandom) MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning); }) {Priority = ThreadPriority.Highest}; loop.Start(); } TestList.Add(rBlock); #endif return rBlock; } #if TEST if (_bufferSize >= 256) { var loop = new Thread(() => { if (!finalBuffer.ChiSquaredTest().isRandom) MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning); }) {Priority = ThreadPriority.Highest}; loop.Start(); } TestList.Add(finalBuffer); #endif return finalBuffer; } private ulong[] ByteArrayToULongArray(byte[] ba, int finalSize) { var minSize = ba.Length / 8; if (finalSize < minSize) finalSize = minSize; ba = PadULong(ba); var result = new ulong[finalSize]; for (var i = 0; i < ba.Length; i += 8) Buffer.BlockCopy(ba, i, result, i, 8); return result; } private static byte[] PadULong(byte[] ba) { var s = ba.Length % 8; switch (s) { case 0: break; case 1: Array.Resize(ref ba, ba.Length + 7); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; ba[ba.Length - 3] = 0x80; ba[ba.Length - 4] = 0x80; ba[ba.Length - 5] = 0x80; ba[ba.Length - 6] = 0x80; ba[ba.Length - 7] = 0x80; break; case 2: Array.Resize(ref ba, ba.Length + 6); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; ba[ba.Length - 3] = 0x80; ba[ba.Length - 4] = 0x80; ba[ba.Length - 5] = 0x80; ba[ba.Length - 6] = 0x80; break; case 3: Array.Resize(ref ba, ba.Length + 5); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; ba[ba.Length - 3] = 0x80; ba[ba.Length - 4] = 0x80; ba[ba.Length - 5] = 0x80; break; case 4: Array.Resize(ref ba, ba.Length + 4); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; ba[ba.Length - 3] = 0x80; ba[ba.Length - 4] = 0x80; break; case 5: Array.Resize(ref ba, ba.Length + 3); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; ba[ba.Length - 3] = 0x80; break; case 6: Array.Resize(ref ba, ba.Length + 2); ba[ba.Length - 1] = 0x80; ba[ba.Length - 2] = 0x80; break; case 7: Array.Resize(ref ba, ba.Length + 1); ba[ba.Length - 1] = 0x80; break; } return ba; } private static void Extrude(ulong[] x) { var size = x.Length; for (var i = 0; i < size; i++) { ulong n = 0; var j = 0; while (j < size) { n ^= x[j]; ++j; } x[i] = (n << 1) | (n >> 56); } } private ulong[] CreateNoiseArrays(byte[] ba) { var ula = ByteArrayToULongArray(ba, ba.Length / 8); Extrude(ula); return ula; } internal class EntropyI { private const double NaturalLogOfTwo = 0.69314718055994530941723212145818; //Math.Log(2); /// <summary> /// Get the Entropy from 1 to 100% 1 being very ordered data, /// 100% being very disordered data. /// </summary> public double Entropy(byte[] a) { var h = new int[256]; var l = a.Length; for (var i = 0; i < l; ++i) h[a[i]]++; var e = 0.0; for (var i = 0; i < 256; ++i) { var v = h[i]; if (v <= 0) continue; var r = v / (double) l; e -= r * (Math.Log(r) / NaturalLogOfTwo); } return e / 8.0 * 100.0; } } #if TEST private EntropyI ent = new EntropyI(); private List<byte[]> TestList = new List<byte[]>(); #endif }
//#define TEST
using System;
using System.Diagnostics;
using System.Management;
using System.Runtime.CompilerServices;
using System.Threading;
[Serializable]
public class JitterEx
{
    private const    int    DesaturationLoopLimit = 500;
    private const    int    UpperCpuLoadLimit     = 90;
    private const    int    LowerCpuLoadLimit     = 10;
    private static   bool   _scaleSet;
    private readonly int    _bufferSize;
    private readonly object _lock = new object();
    private readonly Random _prng;
    private          byte[] _rngCache;
    private          int    _tscLoopLimitCpu  = 10;
    private          int    _tscSampleSizeRam = 18;
    public JitterEx(int buffersize, bool randomize = false)
    {
        _bufferSize = buffersize;
        _rngCache   = new byte[_bufferSize];
        _prng       = new Random();
        Randomize   = randomize;
        SetScale();
    }
    public bool Randomize
    {
        get;
        set;
    }
#if TEST
    public void TestListF()
    {
        var rlst = new List<List<(byte[], int)>>();
        for (var i = 0; i < TestList.Count; i++)
        {
            var f = TestList[i];
            for (var j = i + 1; j < TestList.Count; j++)
            {
                var s = TestList[j];
                rlst.Add(new BMPartialPatternSearch(3).SearchPartialAll(f, s));
            }
        }
    }
#endif
    [MethodImpl(MethodImplOptions.NoOptimization)]
    private float GetCpuSpeed()
    {
        void Loop()
        {
            var i = 0;
            while (true)
                i = i + 1 - 1;
        }
        var cpuCounter = new PerformanceCounter("Processor Information", "% Processor Performance", "_Total");
        var cpuValue   = cpuCounter.NextValue();
        var loop       = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
        var Speed      = 0f;
        lock (_lock)
        {
            loop.Start();
            Thread.Sleep(60);
            cpuValue = cpuCounter.NextValue();
            loop.Abort();
        }
        foreach (ManagementObject obj in new ManagementObjectSearcher("SELECT *, Name FROM Win32_Processor").Get())
        {
            var v = Convert.ToSingle(obj["MaxClockSpeed"]);
            Speed = v / 1000 * cpuValue / 100;
        }
        return Speed;
    }
    /// <summary>
    ///     This is a fairly arbitrary value which is based on the CPU speed. 4.7 is the speed on which the tests are based.
    /// </summary>
    private void SetScale()
    {
        if (_scaleSet)
            return;
        _scaleSet = true;
        const float baseFreq = 4.7f;
        var         thisFreq = GetCpuSpeed();
        var         rat      = baseFreq / thisFreq;
        _tscLoopLimitCpu  = (int) Math.Ceiling(_tscLoopLimitCpu  * rat);
        _tscSampleSizeRam = (int) Math.Ceiling(_tscSampleSizeRam * rat);
    }
    private void LoadBlock()
    {
        var DesaturationLoops = 0;
        var dump              = CpuTotalPc.CPULoad;
        do
        {
            Thread.Sleep(0);
            DesaturationLoops++;
        } while (DesaturationLoops < DesaturationLoopLimit && ((int) CpuTotalPc.CPULoad > UpperCpuLoadLimit || (int) CpuTotalPc.CPULoad < LowerCpuLoadLimit));
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    private byte[] GetBufferCpu()
    {
        void Loop()
        {
            var x = 0;
            for (var i = 0; i < _tscLoopLimitCpu; i++)
                x = x + 1 - 1;
        }
        var jitterBuffer = new byte[_bufferSize];
        var ptr          = 0;
        LoadBlock();
        lock (_lock)
        {
            var start = Rdtsc.TimestampP();
            do
            {
                var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
                loop.Start();
                loop.Join();
                var stop = Rdtsc.TimestampP();
                Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
                start =  stop;
                ptr   += 4;
            } while (ptr < _bufferSize);
            return jitterBuffer;
        }
    }
    [MethodImpl(MethodImplOptions.NoInlining)]
    private unsafe byte[] GetBufferRam()
    {
        void Loop()
        {
            byte tempByte;
            fixed (byte* p1 = _rngCache)
            {
                var x1 = p1;
                for (var j = 0; j < _tscSampleSizeRam; ++j, ++x1)
                    tempByte = *x1;
            }
        }
        LoadBlock();
        var jitterBuffer = new byte[_bufferSize];
        lock (_lock)
        {
            if (_rngCache.Length != _bufferSize)
                _rngCache = new byte[_bufferSize];
            _prng.NextBytes(_rngCache);
            var ptr   = 0;
            var start = Rdtsc.TimestampP();
            while (true)
            {
                do
                {
                    var loop = new Thread(() => Loop()) {Priority = ThreadPriority.Highest};
                    loop.Start();
                    loop.Join();
                    var stop = Rdtsc.TimestampP();
                    Buffer.BlockCopy((100000.0 / ((stop - start) * 100000.0)).GetBytes(), 0, jitterBuffer, ptr, 4);
                    start =  stop;
                    ptr   += 4;
                    if (ptr < _bufferSize)
                    {
                        if (_rngCache.Length != _bufferSize)
                            _rngCache = new byte[_bufferSize];
                        _prng.NextBytes(_rngCache);
                    }
                } while (ptr < _bufferSize);
                return jitterBuffer;
            }
        }
    }
    public byte[] GetBuffer()
    {
        var firstBuffer = GetBufferCpu();
#if TEST
        ///Weighting add 15%, perfection is not what we are looking for here.
        var lim = _bufferSize <= 256 ? _bufferSize / 256.0 * 85.0 : 6.8;
        if (ent.Entropy(firstBuffer) < lim)
            throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
        var secondBuffer = GetBufferRam();
#if TEST
        if (ent.Entropy(secondBuffer) < lim)
            throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
        var finalBuffer = new byte[_bufferSize];
        for (var j = 0; j < _bufferSize; ++j)
            finalBuffer[j] = (byte) (firstBuffer[j] ^ secondBuffer[j]);
#if TEST
        if (ent.Entropy(finalBuffer) < lim)
            throw new Exception("Error CPU Jitter Buffer Contains only zeros.");
#endif
        if (Randomize)
        {
            var ula    = CreateNoiseArrays(finalBuffer);
            var rBlock = new byte[ula.Length * 8];
            Buffer.BlockCopy(ula, 0, rBlock, 0, ula.Length * 8);
#if TEST
            if (_bufferSize >= 256)
            {
                var loop = new Thread(() =>
                {
                    if (!rBlock.ChiSquaredTest().isRandom)
                        MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);
                }) {Priority = ThreadPriority.Highest};
                loop.Start();
            }
            TestList.Add(rBlock);
#endif
            return rBlock;
        }
#if TEST
        if (_bufferSize >= 256)
        {
            var loop = new Thread(() =>
            {
                if (!finalBuffer.ChiSquaredTest().isRandom)
                    MessageBoxEx.Show("Warning", "Block not random.", MessageBoxExButtons.OK, MessageBoxExIcon.Warning);
            }) {Priority = ThreadPriority.Highest};
            loop.Start();
        }
        TestList.Add(finalBuffer);
#endif
        return finalBuffer;
    }
    private ulong[] ByteArrayToULongArray(byte[] ba, int finalSize)
    {
        var minSize = ba.Length / 8;
        if (finalSize < minSize)
            finalSize = minSize;
        ba = PadULong(ba);
        var result = new ulong[finalSize];
        for (var i = 0; i < ba.Length; i += 8)
            Buffer.BlockCopy(ba, i, result, i, 8);
        return result;
    }
    private static byte[] PadULong(byte[] ba)
    {
        var s = ba.Length % 8;
        switch (s)
        {
            case 0:
                break;
            case 1:
                Array.Resize(ref ba, ba.Length + 7);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                ba[ba.Length - 6] = 0x80;
                ba[ba.Length - 7] = 0x80;
                break;
            case 2:
                Array.Resize(ref ba, ba.Length + 6);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                ba[ba.Length - 6] = 0x80;
                break;
            case 3:
                Array.Resize(ref ba, ba.Length + 5);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                ba[ba.Length - 5] = 0x80;
                break;
            case 4:
                Array.Resize(ref ba, ba.Length + 4);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                ba[ba.Length - 4] = 0x80;
                break;
            case 5:
                Array.Resize(ref ba, ba.Length + 3);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                ba[ba.Length - 3] = 0x80;
                break;
            case 6:
                Array.Resize(ref ba, ba.Length + 2);
                ba[ba.Length - 1] = 0x80;
                ba[ba.Length - 2] = 0x80;
                break;
            case 7:
                Array.Resize(ref ba, ba.Length + 1);
                ba[ba.Length - 1] = 0x80;
                break;
        }
        return ba;
    }
    private static void Extrude(ulong[] x)
    {
        var size = x.Length;
        for (var i = 0; i < size; i++)
        {
            ulong n = 0;
            var   j = 0;
            while (j < size)
            {
                n ^= x[j];
                ++j;
            }
            x[i] = (n << 1) | (n >> 56);
        }
    }
    private ulong[] CreateNoiseArrays(byte[] ba)
    {
        var ula = ByteArrayToULongArray(ba, ba.Length / 8);
        Extrude(ula);
        return ula;
    }
    internal class EntropyI
    {
        private const double NaturalLogOfTwo = 0.69314718055994530941723212145818; //Math.Log(2);
        /// <summary>
        ///     Get the Entropy from 1 to 100% 1 being very ordered data,
        ///     100% being very disordered data.
        /// </summary>
        public double Entropy(byte[] a)
        {
            var h = new int[256];
            var l = a.Length;
            for (var i = 0; i < l; ++i)
                h[a[i]]++;
            var e = 0.0;
            for (var i = 0; i < 256; ++i)
            {
                var v = h[i];
                if (v <= 0)
                    continue;
                var r = v             / (double) l;
                e -= r * (Math.Log(r) / NaturalLogOfTwo);
            }
            return e / 8.0 * 100.0;
        }
    }
#if TEST
    private EntropyI     ent = new EntropyI();
    private List<byte[]> TestList = new List<byte[]>();
#endif
}