Created
January 12, 2021 14:19
-
-
Save mjs3339/808c4a3bfa2aa48a33868940da052f14 to your computer and use it in GitHub Desktop.
Jitter Cache
This file contains 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.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(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment