{"id":158,"date":"2020-08-06T07:17:53","date_gmt":"2020-08-06T07:17:53","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=158"},"modified":"2020-08-06T07:30:57","modified_gmt":"2020-08-06T07:30:57","slug":"ksm128cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/08\/06\/ksm128cs\/","title":{"rendered":"KSM128.cs"},"content":{"rendered":"\n<p>Re-Work of the Sha3 Keccak Sponge for 128 Bit Hashing<\/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;\nusing System.Runtime.CompilerServices;\npublic class KSM128 : HashAlgorithmEx\n{\n    private readonly int _outputLength;\n    private readonly int _rateBytes;\n    private readonly ulong[] _roundConstants =\n    {\n        0x0000000000000001,\n        0x0000000000008082,\n        0x800000000000808A,\n        0x8000000080008000,\n        0x000000000000808B,\n        0x0000000080000001,\n        0x8000000080008081,\n        0x8000000000008009,\n        0x000000000000008A,\n        0x0000000000000088,\n        0x0000000080008009,\n        0x000000008000000A,\n        0x000000008000808B,\n        0x800000000000008B,\n        0x8000000000008089,\n        0x8000000000008003,\n        0x8000000000008002,\n        0x8000000000000080,\n        0x000000000000800A,\n        0x800000008000000A,\n        0x8000000080008081,\n        0x8000000000008080,\n        0x0000000080000001,\n        0x8000000080008008\n    };\n    private readonly ulong[] _seed;\n    private          int     _blockSize;\n    private          int     _input;\n    private          int     _output;\n    private          byte[]  _result;\n    private          ulong[] _state;\n    public           int     HashLength;\n    public           int     Rounds = 24;\n    public KSM128(int size, int rounds = 24, ulong[] seed = null)\n    {\n        if (rounds > 24)\n            throw new Exception($\"Maximum rounds allowed is {24}\");\n        var MaxBR     = (64 >> 3) * 5;\n        var sizeBytes = size >> 3;\n        var rateBytes = MaxBR - (sizeBytes &lt;&lt; 1);\n        var MaxSize   = ((MaxBR - 8)       >> 1) &lt;&lt; 3;\n        if (rateBytes &lt; 8)\n            throw new Exception($\"Maximum size allowed is {MaxSize} Bits with {128} bit Width specified. Specified Size is {size} Bits.\");\n        var outputLength = size >> 3;\n        _rateBytes    = rateBytes;\n        _outputLength = outputLength;\n        HashLength    = outputLength;\n        _seed         = seed;\n    }\n    public override void Initialize()\n    {\n        _blockSize = 0;\n        _input     = 0;\n        _output    = 0;\n        _state     = new ulong[5];\n        _result    = new byte[_outputLength];\n        if (_seed != null &amp;&amp; _seed[0] != 0)\n        {\n            for (var i = 0; i &lt; _seed.Length &amp;&amp; i &lt; _state.Length; ++i)\n                _state[i] = _seed[i];\n            Permute(_state);\n        }\n    }\n    public void Absorb(byte[] array, int start, int size)\n    {\n        while (size > 0)\n        {\n            _blockSize = Math.Min(size, _rateBytes);\n            for (var index = start; index &lt; _blockSize; ++index)\n            {\n                var num = Convert.ToByte(Buffer.GetByte(_state, index) ^ array[index + _input]);\n                Buffer.SetByte(_state, index, num);\n            }\n            _input += _blockSize;\n            size   -= _blockSize;\n            if (_blockSize == _rateBytes)\n            {\n                Permute(_state);\n                _blockSize = 0;\n            }\n        }\n    }\n    public byte[] Squeeze()\n    {\n        Buffer.SetByte(_state, _blockSize,     Convert.ToByte(Buffer.GetByte(_state, _blockSize)     ^ 6));\n        Buffer.SetByte(_state, _rateBytes - 1, Convert.ToByte(Buffer.GetByte(_state, _rateBytes - 1) ^ 128));\n        Permute(_state);\n        var outputLength = _outputLength;\n        while (outputLength > 0)\n        {\n            _blockSize = Math.Min(outputLength, _rateBytes);\n            Buffer.BlockCopy(_state, 0, _result, _output, _blockSize);\n            _output      += _blockSize;\n            outputLength -= _blockSize;\n            if (outputLength > 0)\n                Permute(_state);\n        }\n        return _result;\n    }\n    [MethodImpl(MethodImplOptions.AggressiveInlining)]\n    private void Permute(ulong[] state)\n    {\n        for (var round = 0; round &lt; Rounds; ++round)\n        {\n            Theta(out var C0, state, out var C1, out var C2, out var C3, out var C4);\n            RhoPi(state);\n            Chi(ref C0, state, ref C1, ref C2, ref C3, ref C4);\n            Iota(round, state);\n        }\n    }\n    private static void Theta(out ulong C0, ulong[] state, out ulong C1, out ulong C2, out ulong C3, out ulong C4)\n    {\n        C0 = state[0] ^ state[4];\n        C1 = state[1] ^ state[0];\n        C2 = state[2] ^ state[1];\n        C3 = state[3] ^ state[2];\n        C4 = state[4] ^ state[3];\n        var D0 = Rol(C1, 1) ^ C4;\n        var D1 = Rol(C2, 1) ^ C0;\n        var D2 = Rol(C3, 1) ^ C1;\n        var D3 = Rol(C4, 1) ^ C2;\n        var D4 = Rol(C0, 1) ^ C3;\n        state[0] ^= D0;\n        state[1] ^= D1;\n        state[2] ^= D2;\n        state[3] ^= D3;\n        state[4] ^= D4;\n    }\n    private static void RhoPi(ulong[] state)\n    {\n        var a = Rol(state[1], 1);\n        state[1] = Rol(state[4], 44);\n        state[4] = Rol(state[3], 43);\n        state[3] = Rol(state[2], 14);\n        state[4] = Rol(state[1], 21);\n        state[2] = a;\n    }\n    private void Iota(int round, ulong[] state)\n    {\n        state[0] ^= _roundConstants[round];\n    }\n    private static void Chi(ref ulong C0, ulong[] state, ref ulong C1, ref ulong C2, ref ulong C3, ref ulong C4)\n    {\n        C0       = state[0] ^ (~state[1] &amp; state[2]);\n        C1       = state[1] ^ (~state[2] &amp; state[3]);\n        C2       = state[2] ^ (~state[3] &amp; state[4]);\n        C3       = state[3] ^ (~state[4] &amp; state[0]);\n        C4       = state[4] ^ (~state[0] &amp; state[1]);\n        state[0] = C0;\n        state[1] = C1;\n        state[2] = C2;\n        state[3] = C3;\n        state[4] = C4;\n    }\n    [MethodImpl(MethodImplOptions.AggressiveInlining)]\n    private static ulong Rol(ulong x, byte y)\n    {\n        return (x &lt;&lt; y) | (x >> (64 - y));\n    }\n    protected override void HashCore(byte[] array, int ibStart, int cbSize)\n    {\n        Initialize();\n        Absorb(array, ibStart, cbSize);\n    }\n    protected override byte[] HashFinal()\n    {\n        return Squeeze();\n    }\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Re-Work of the Sha3 Keccak Sponge for 128 Bit Hashing<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[67,74,21],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/158"}],"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=158"}],"version-history":[{"count":3,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/158\/revisions"}],"predecessor-version":[{"id":161,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/158\/revisions\/161"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=158"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=158"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=158"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}