{"id":57,"date":"2020-06-08T09:41:12","date_gmt":"2020-06-08T09:41:12","guid":{"rendered":"https:\/\/michaeljohnsteiner.com\/?p=57"},"modified":"2020-06-08T09:41:12","modified_gmt":"2020-06-08T09:41:12","slug":"keccakspongemanaged-cs","status":"publish","type":"post","link":"https:\/\/michaeljohnsteiner.com\/index.php\/2020\/06\/08\/keccakspongemanaged-cs\/","title":{"rendered":"KeccakSpongeManaged.cs"},"content":{"rendered":"\n<p>Keccak Sponge (Sha3) Checked<\/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;\n[Serializable]\npublic class SHA3Managed : HashAlgorithmEx\n{\n    private readonly KeccakSpongeManaged ksm;\n    public SHA3Managed(int size, ulong[] seed = null) : this(size, 24, seed)\n    {\n    }\n    public SHA3Managed(int size) : this(size, 24)\n    {\n    }\n    public SHA3Managed() : this(512, 24)\n    {\n    }\n    public SHA3Managed(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) * 25;\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 {64} bit Width specified. Specified Size is {size} Bits.\");\n        var outputLength = size >> 3;\n        ksm           = new KeccakSpongeManaged(rateBytes, 200 - rateBytes, KeccakSpongeManaged.KeccakDelimiter, outputLength, seed);\n        ksm.Rounds    = rounds;\n        HashSizeValue = size;\n    }\n    public int HashLength => ksm.HashLength;\n    public override void Initialize()\n    {\n        ksm.Initialize();\n    }\n    protected override void HashCore(byte[] array, int ibStart, int cbSize)\n    {\n        Initialize();\n        ksm.Absorb(array, ibStart, cbSize);\n    }\n    protected override byte[] HashFinal()\n    {\n        return ksm.Squeeze();\n    }\n}\n[Serializable]\npublic class KeccakSpongeManaged\n{\n    public const     int KeccakDelimiter = 6;\n    public const     int ShakeDelimiter  = 31;\n    private readonly int _delimiter;\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 KeccakSpongeManaged(int rateBytes, int capacityBytes, int delimiter, int outputLength, ulong[] seed)\n    {\n        if (rateBytes + capacityBytes != 200 || (uint) (rateBytes % 8) > 0U)\n            throw new ArgumentException($\"rateBytes {rateBytes} + capacityBytes {capacityBytes}={rateBytes + capacityBytes} must be 200 or {rateBytes} must be a multiple of 8\");\n        _rateBytes    = rateBytes;\n        _delimiter    = delimiter;\n        _outputLength = outputLength;\n        HashLength    = outputLength;\n        _seed         = seed;\n    }\n    public void Initialize()\n    {\n        _blockSize = 0;\n        _input     = 0;\n        _output    = 0;\n        _state     = new ulong[25];\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) ^ _delimiter));\n        if ((_delimiter &amp; 128) != 0 &amp;&amp; _blockSize == _rateBytes - 1)\n            Permute(_state);\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[5] ^ state[10] ^ state[15] ^ state[20];\n        C1 = state[1] ^ state[6] ^ state[11] ^ state[16] ^ state[21];\n        C2 = state[2] ^ state[7] ^ state[12] ^ state[17] ^ state[22];\n        C3 = state[3] ^ state[8] ^ state[13] ^ state[18] ^ state[23];\n        C4 = state[4] ^ state[9] ^ state[14] ^ state[19] ^ state[24];\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[5]  ^= D0;\n        state[10] ^= D0;\n        state[15] ^= D0;\n        state[20] ^= D0;\n        state[1]  ^= D1;\n        state[6]  ^= D1;\n        state[11] ^= D1;\n        state[16] ^= D1;\n        state[21] ^= D1;\n        state[2]  ^= D2;\n        state[7]  ^= D2;\n        state[12] ^= D2;\n        state[17] ^= D2;\n        state[22] ^= D2;\n        state[3]  ^= D3;\n        state[8]  ^= D3;\n        state[13] ^= D3;\n        state[18] ^= D3;\n        state[23] ^= D3;\n        state[4]  ^= D4;\n        state[9]  ^= D4;\n        state[14] ^= D4;\n        state[19] ^= D4;\n        state[24] ^= D4;\n    }\n    private static void RhoPi(ulong[] state)\n    {\n        var a = Rol(state[1], 1);\n        state[1]  = Rol(state[6],  44);\n        state[6]  = Rol(state[9],  20);\n        state[9]  = Rol(state[22], 61);\n        state[22] = Rol(state[14], 39);\n        state[14] = Rol(state[20], 18);\n        state[20] = Rol(state[2],  62);\n        state[2]  = Rol(state[12], 43);\n        state[12] = Rol(state[13], 25);\n        state[13] = Rol(state[19], 8);\n        state[19] = Rol(state[23], 56);\n        state[23] = Rol(state[15], 41);\n        state[15] = Rol(state[4],  27);\n        state[4]  = Rol(state[24], 14);\n        state[24] = Rol(state[21], 2);\n        state[21] = Rol(state[8],  55);\n        state[8]  = Rol(state[16], 45);\n        state[16] = Rol(state[5],  36);\n        state[5]  = Rol(state[3],  28);\n        state[3]  = Rol(state[18], 21);\n        state[18] = Rol(state[17], 15);\n        state[17] = Rol(state[11], 10);\n        state[11] = Rol(state[7],  6);\n        state[7]  = Rol(state[10], 3);\n        state[10] = 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        for (var index = 0; index &lt; 25; index += 5)\n        {\n            C0               = state[index]     ^ (~state[1 + index] &amp; state[2 + index]);\n            C1               = state[1 + index] ^ (~state[2 + index] &amp; state[3 + index]);\n            C2               = state[2 + index] ^ (~state[3 + index] &amp; state[4 + index]);\n            C3               = state[3 + index] ^ (~state[4 + index] &amp; state[index]);\n            C4               = state[4 + index] ^ (~state[index]     &amp; state[1 + index]);\n            state[index]     = C0;\n            state[1 + index] = C1;\n            state[2 + index] = C2;\n            state[3 + index] = C3;\n            state[4 + index] = C4;\n        }\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}<\/pre>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Keccak Sponge (Sha3) Checked<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[2],"tags":[],"_links":{"self":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/57"}],"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=57"}],"version-history":[{"count":1,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/57\/revisions"}],"predecessor-version":[{"id":58,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/posts\/57\/revisions\/58"}],"wp:attachment":[{"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/media?parent=57"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/categories?post=57"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/michaeljohnsteiner.com\/index.php\/wp-json\/wp\/v2\/tags?post=57"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}