{"id":114,"date":"2020-07-27T04:21:15","date_gmt":"2020-07-27T04:21:15","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=114"},"modified":"2020-07-30T08:33:13","modified_gmt":"2020-07-30T08:33:13","slug":"arraymixer-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/07\/27\/arraymixer-cs\/","title":{"rendered":"ArrayMixer.cs"},"content":{"rendered":"\n<p>Uses Sha3 to Shuffle Primitive Arrays <\/p>\n\n\n\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;\npublic class ArrayMixer\n{\n    private readonly SHA3ModInt _alg;\n    private readonly int        _moveSize;\n    public ArrayMixer() : this(256, 24)\n    {\n    }\n    public ArrayMixer(int hashSize) : this(hashSize, 24)\n    {\n    }\n    public ArrayMixer(int hashSize, int rounds)\n    {\n        _alg      = new SHA3ModInt(hashSize, rounds);\n        _moveSize = _alg.ComputeHash(2.GetBytes()).Length;\n    }\n    public byte[] Mix(byte[] buf, int iterations = 1000)\n    {\n        var bufferSize = buf.Length;\n        var lBuffer    = new byte[_moveSize];\n        var oBuffer    = new byte[bufferSize];\n        for (var i = 0; i &lt; iterations; ++i)\n        {\n            var bytesSuffled = 0;\n            var moveSize     = _moveSize;\n            var p            = 0;\n            while (true)\n            {\n                var rBytesShuffle = bufferSize - bytesSuffled;\n                if (rBytesShuffle &lt; moveSize)\n                    moveSize = rBytesShuffle;\n                if (rBytesShuffle &lt;= 0)\n                    break;\n                Buffer.BlockCopy(buf, p, lBuffer, 0, moveSize);\n                lBuffer = _alg.ComputeHash(lBuffer);\n                Buffer.BlockCopy(lBuffer, 0, oBuffer, p, moveSize);\n                p            += moveSize;\n                bytesSuffled += moveSize;\n            }\n            Buffer.BlockCopy(oBuffer, 0, buf, 0, bufferSize);\n        }\n        lBuffer.Fill(0);\n        oBuffer.Fill(0);\n        return buf;\n    }\n    public ushort[] Mix(ushort[] buf, int iterations = 1000)\n    {\n        var bb = buf.GetBytes();\n        return Mix(bb, iterations).ToUShortArray();\n    }\n    public uint[] Mix(uint[] buf, int iterations = 1000)\n    {\n        var bb = buf.GetBytes();\n        return Mix(bb, iterations).ToUIntArray();\n    }\n    public ulong[] Mix(ulong[] buf, int iterations = 1000)\n    {\n        var bb = buf.GetBytes();\n        return Mix(bb, iterations).ToULongArray();\n    }\n    \/\/\/ &lt;summary>\n    \/\/\/     Will round up finalSize to the nearest 8 byte boundary.\n    \/\/\/ &lt;\/summary>\n    \/\/\/ &lt;param name=\"ba\">&lt;\/param>\n    \/\/\/ &lt;param name=\"finalSize\">&lt;\/param>\n    \/\/\/ &lt;returns>&lt;\/returns>\n    private static ulong[] ByteArrayToULongArray(byte[] ba, int finalSize)\n    {\n        var minSize = ba.Length \/ 8;\n        if (finalSize &lt; minSize)\n            finalSize = minSize;\n        ba = PadULong(ba);\n        var os = finalSize \/ 8;\n        if (os * 8 &lt; finalSize)\n            os++;\n        var result = new ulong[os];\n        for (var i = 0; i &lt; ba.Length; i += 8)\n            Buffer.BlockCopy(ba, i, result, i, 8);\n        return result;\n    }\n    private static byte[] PadULong(byte[] ba)\n    {\n        var s = ba.Length % 8;\n        switch (s)\n        {\n            case 0:\n                break;\n            case 1:\n                Array.Resize(ref ba, ba.Length + 7);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                ba[ba.Length - 6] = 0x80;\n                ba[ba.Length - 7] = 0x80;\n                break;\n            case 2:\n                Array.Resize(ref ba, ba.Length + 6);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                ba[ba.Length - 6] = 0x80;\n                break;\n            case 3:\n                Array.Resize(ref ba, ba.Length + 5);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                ba[ba.Length - 5] = 0x80;\n                break;\n            case 4:\n                Array.Resize(ref ba, ba.Length + 4);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                ba[ba.Length - 4] = 0x80;\n                break;\n            case 5:\n                Array.Resize(ref ba, ba.Length + 3);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                ba[ba.Length - 3] = 0x80;\n                break;\n            case 6:\n                Array.Resize(ref ba, ba.Length + 2);\n                ba[ba.Length - 1] = 0x80;\n                ba[ba.Length - 2] = 0x80;\n                break;\n            case 7:\n                Array.Resize(ref ba, ba.Length + 1);\n                ba[ba.Length - 1] = 0x80;\n                break;\n        }\n        return ba;\n    }\n    private static void Expand(ulong[] x, int iterations = 1)\n    {\n        var size = x.Length;\n        for (var k = 0; k &lt; iterations; ++k)\n        for (var i = 0; i &lt; size; ++i)\n        {\n            ulong n = 0;\n            var   j = 0;\n            while (j &lt; size)\n            {\n                n ^= x[j];\n                ++j;\n            }\n            x[i] = (n &lt;&lt; 1) | (n >> 56);\n        }\n    }\n    \/\/\/ &lt;summary>\n    \/\/\/     ExpandAndMixArray resizes the array by extrusion then mixes the array using a Sha3 one way hash\n    \/\/\/ &lt;\/summary>\n    \/\/\/ &lt;param name=\"ba\">The buffer&lt;\/param>\n    \/\/\/ &lt;param name=\"size\">The final desired size&lt;\/param>\n    \/\/\/ &lt;param name=\"iterations\">The number of iterations to mix the final array&lt;\/param>\n    public byte[] ExpandAndMixArray(byte[] ba, int size, int iterations = 1000)\n    {\n        var ula = ByteArrayToULongArray(ba, size);\n        Expand(ula, 1);\n        var array = ula.GetBytes();\n        return Mix(array, iterations);\n    }\n    public ushort[] ExpandAndMixArray(ushort[] ba, int size, int iterations = 1000)\n    {\n        var bb = ba.GetBytes();\n        return ExpandAndMixArray(bb, size, iterations).ToUShortArray();\n    }\n    public uint[] ExpandAndMixArray(uint[] ba, int size, int iterations = 1000)\n    {\n        var bb = ba.GetBytes();\n        return ExpandAndMixArray(bb, size, iterations).ToUIntArray();\n    }\n    public ulong[] ExpandAndMixArray(ulong[] ba, int size, int iterations = 1000)\n    {\n        var bb = ba.GetBytes();\n        return ExpandAndMixArray(bb, size, iterations).ToULongArray();\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Uses Sha3 to Shuffle Primitive Arrays<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[35,19,51,21,50],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/114"}],"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=114"}],"version-history":[{"count":3,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/114\/revisions"}],"predecessor-version":[{"id":119,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/114\/revisions\/119"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=114"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=114"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=114"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}