{"id":13,"date":"2020-06-04T07:43:33","date_gmt":"2020-06-04T07:43:33","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=13"},"modified":"2020-06-28T14:08:21","modified_gmt":"2020-06-28T14:08:21","slug":"jittercacherng-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/04\/jittercacherng-cs\/","title":{"rendered":"JitterCacheRng.cs"},"content":{"rendered":"\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System;\nusing System.Security.Cryptography;\nusing System.Threading;\n[Serializable]\npublic class JitterCacheRng : RandomNumberGenerator\n{\n    private const    int        ReSecureThreshold = 10;\n    private readonly SHA3ModInt _algorithm;\n    private readonly JitterEx   _jit;\n    private readonly int        _moveSize;\n    private          int        _availableCacheBytes;\n    private          byte[]     _cache;\n    private          byte[]     _cacheBuffer;\n    private          int        _cacheSize;\n    private          int        _ptr;\n    public           int        cacheFills;\n    public JitterCacheRng() : this(1048576, 256, 256, 4)\n    {\n    }\n    public JitterCacheRng(int cacheSize) : this(cacheSize, 256, 256, 4)\n    {\n    }\n    public JitterCacheRng(int cacheSize, int seedSize) : this(cacheSize, seedSize, 256, 4)\n    {\n    }\n    public JitterCacheRng(int cacheSize, int seedSize, int sha3Size) : this(cacheSize, seedSize, sha3Size, 4)\n    {\n    }\n    public JitterCacheRng(int cacheSize, int seedSize, int sha3Size, int sha3Rounds)\n    {\n        if (cacheSize == 0)\n            throw new ArgumentException(\"Cache Size cannot be zero\");\n        if (seedSize &lt; 256)\n            throw new ArgumentException(\"The seed size should be 256 or more bytes.\");\n        if (sha3Size &lt; 64 &amp;&amp; sha3Size % 64 != 0)\n            throw new ArgumentException(\"The bitWidth of the SHA3 hash algorithm need to be at least 64 bits and a multiple of 64.\");\n        if (sha3Rounds &lt; 4)\n            throw new ArgumentException(\"Sha3 rounds of less than 4 might produce some short run repetitive sequences.\");\n        _cacheSize   = cacheSize;\n        _jit         = new JitterEx(seedSize);\n        _cacheBuffer = _jit.GetBuffer();\n        _cache       = new byte[_cacheSize];\n        _algorithm   = new SHA3ModInt(sha3Size, sha3Rounds);\n        _moveSize    = _algorithm.ComputeHash(2.GetBytes()).Length;\n        FillCache();\n    }\n    public bool Protect\n    {\n        get;\n        set;\n    }\n    protected override void Dispose(bool disposing)\n    {\n        _cache.Fill(0);\n        _availableCacheBytes = 0;\n        _algorithm.Dispose();\n    }\n    public override void GetBytes(byte[] data)\n    {\n        if (data.Length > _cacheSize)\n        {\n            _cacheSize = data.Length;\n            _cache     = new byte[_cacheSize];\n            FillCache();\n        }\n        if (_availableCacheBytes == 0 || _availableCacheBytes &lt; data.Length)\n        {\n            if (_cacheSize &lt; data.Length)\n            {\n                _cacheSize = data.Length;\n                _cache     = new byte[_cacheSize];\n            }\n            FillCache();\n        }\n        if (_ptr + data.Length > _cacheSize)\n            FillCache();\n        if (Protect)\n            ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);\n        Buffer.BlockCopy(_cache, _ptr, data, 0, data.Length);\n        if (Protect)\n            ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);\n        _ptr                 += data.Length;\n        _availableCacheBytes -= data.Length;\n    }\n    private void FillCache()\n    {\n        var btrd = new Thread(() =>\n        {\n            _availableCacheBytes = 0;\n            _ptr                 = 0;\n            var p        = 0;\n            var moveSize = _moveSize;\n            cacheFills++;\n            if (cacheFills % ReSecureThreshold == 0)\n                _cacheBuffer = _jit.GetBuffer();\n            if (Protect)\n                ProtectedMemory.Unprotect(_cache, MemoryProtectionScope.SameLogon);\n            while (true)\n            {\n                var remainingBytesToMove = _cacheSize - _availableCacheBytes;\n                if (remainingBytesToMove &lt; moveSize)\n                    moveSize = remainingBytesToMove;\n                if (remainingBytesToMove &lt;= 0)\n                    break;\n                _cacheBuffer = _algorithm.ComputeHash(_cacheBuffer);\n                Buffer.BlockCopy(_cacheBuffer, 0, _cache, p, moveSize);\n                p                    += moveSize;\n                _availableCacheBytes += moveSize;\n            }\n            if (Protect)\n                ProtectedMemory.Protect(_cache, MemoryProtectionScope.SameLogon);\n        }) {Priority = ThreadPriority.Highest};\n        btrd.Start();\n        btrd.Join();\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[42,15,40],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/13"}],"collection":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/comments?post=13"}],"version-history":[{"count":3,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/13\/revisions"}],"predecessor-version":[{"id":97,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/13\/revisions\/97"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}