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(); } }
One thought on “JitterCacheRng.cs”