Created
July 20, 2020 20:52
-
-
Save mjs3339/0da0d0d484e89461318f1f62f8252843 to your computer and use it in GitHub Desktop.
Detect Entropy Levels from Primitive Data Arrays
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
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(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment